Comparison

Vireya vs Radix UI

The de-facto standard for unstyled, accessible React primitives, plus an optional pre-styled Themes layer.

Two different bets

Radix UI has quietly become the accessibility backbone of the modern React ecosystem. Its Primitives are unstyled, behaviour-only building blocks — dialogs, dropdown menus, popovers, tooltips, accordions — that handle the genuinely hard parts: focus trapping, keyboard navigation, ARIA wiring, controlled and uncontrolled state, portalling and collision-aware positioning. They render close to bare DOM and ship no opinions about how anything looks, which is exactly why so many libraries (shadcn/ui among them) are built on top of them.

Radix also offers a second tier, Radix Themes, which layers a configurable, pre-styled component set over those primitives with an accent/gray/radius/scaling theming model. So the project actually spans two standpoints: raw primitives where you own every pixel of the visual layer, and Themes where you accept Radix's design language for speed. Most teams reach for the Primitives and supply the CSS themselves.

Vireya isn't really a like-for-like competitor to Radix — it sits a layer above it. Vireya consumes Radix (alongside base-ui) for accessible behaviour, then adds the part Radix Primitives deliberately leave undone: finished, styled components driven by a `--v-*` design-token system, plus pre-composed blocks and a charts library that share that same token vocabulary. In other words, the accessibility you'd get from wiring up Radix yourself is already inside Vireya's components.

The honest framing is one of layers, not rivalry. If you want primitives to style from scratch into a bespoke design system, Radix is the foundation to reach for — and you may well end up using it directly. If you want the styling, theming and composition already done on top of those same kinds of primitives, Vireya hands you that finished surface. Vireya is early (v0.1.0) and far less widely adopted than Radix, so this is a comparison of where each sits in the stack, not of maturity.

Under the hood

Layers: unstyled primitives vs styled components on top of them

Radix Primitives give you behaviour and structure with no styling — each component renders semantic, accessible DOM and exposes data attributes (`data-state`, `data-side`, and so on) plus an `asChild` slot pattern so you attach your own classes and elements. The styling is entirely yours to author, in whatever CSS technology you prefer.

Vireya occupies the layer directly above that. It builds its components on Radix and base-ui primitives for the accessible behaviour, then ships the CSS for you as static CSS Modules wired to `--v-*` tokens. You're not choosing between Radix and Vireya so much as choosing whether you author the visual layer over primitives yourself or take Vireya's finished one.

Theming: bring-your-own CSS (or Themes presets) vs a token engine

With Radix Primitives there is no theme to configure — styling lives entirely in your own CSS. Radix Themes adds a provider with a fixed set of knobs (accent color, gray scale, radius, scaling), which is fast but constrains you to that system's design decisions.

Vireya themes through `createTheme()`: a tier-based palette with light/dark and runtime switching, where one token layer drives components, blocks and charts together. You re-theme by changing token values once rather than restyling primitives or staying inside a preset's accent/gray dials.

Scope: primitives only vs components + blocks + charts

Radix is deliberately narrow — accessible interaction primitives (and, in Themes, the components built from them). Data visualisation, page-level compositions and dashboards are out of scope and assembled from other libraries.

Vireya bundles pre-composed blocks and a tokenized charts library next to the components, all sharing one token vocabulary, so a landing page, an app shell and a chart stay visually coherent without stitching separate projects together. Radix has neither blocks nor charts.

Reaching mobile: web-only vs hybrid delivery

Radix Primitives render to the DOM — they're a web concern by design, and Radix Themes is the same. Reaching iOS and Android means a separate React Native effort with different primitives entirely; nothing about Radix follows you to a native target.

Vireya layers a hybrid delivery model on top of those same kinds of primitives. You build the UI once as a web app and run it inside a native WebView shell, with a typed RPC bridge (`@vireya/rpc`) wiring native functions — payments, sensors, push — while screens render from the web. It's the Mobile Bridge pattern Shopify documented and that commerce apps like Mercado Livre and Magazine Luiza ship at scale, so the styled, accessible UI you build on Radix-grade behaviour can reach mobile without a React Native rewrite. The bridge is still maturing (Expo first via `@vireya/platform-expo`), so it's the model Vireya is designed around rather than a finished feature.

Side by side

 VireyaRadix UI
What you getStyled, themed components + blocks + chartsUnstyled primitives (Themes adds a styled set)
LayerSits on top of primitives, ships finished UIThe primitive layer itself
StylingCSS Modules + --v-* tokens, no runtime CSSBring your own (Primitives); Themes ships CSS
ThemingToken engine, tier-based palette, light/darkNone (Primitives); accent/gray/radius/scaling (Themes)
Charts & blocksBundled, same tokensNone
Native mobileHybrid: web UI in a native WebView + typed bridgeWeb / DOM only
AccessibilityBuilt on Radix + base-uiBest-in-class primitives (Vireya builds on these)
MaturityEarly (v0.1.0), actively builtMature, very widely adopted

Where Radix UI shines

What Vireya does differently

When to choose Radix UI

When to choose Vireya

Switching from Radix UI to Vireya

If you're hand-styling Radix Primitives today, moving to Vireya is mostly about deleting CSS rather than rewriting logic. Because Vireya builds on Radix (plus base-ui), the component mental model carries straight over — dialogs, dropdowns, popovers, tooltips and accordions behave the way you already expect, with the same kind of controlled/uncontrolled state and accessible focus handling.

The change is that the styling you previously authored per primitive becomes Vireya's tokenized CSS Modules: you map your palette, spacing and radius onto `--v-*` tokens once via `createTheme()` instead of maintaining stylesheets for every primitive. Teams migrating from Radix Themes trade its accent/gray/radius presets for the broader token engine. Both can coexist during a transition, so you can swap surface by surface and drop your custom primitive styling as Vireya equivalents land.

The bottom line

Radix UI and Vireya live at different layers of the same stack, which is why Vireya uses Radix rather than competing with it. If you want behaviour-only primitives to style into your own design system — or you're already deep in Radix and happy authoring CSS — Radix is the proven, ubiquitous foundation. If you'd rather receive finished, accessible components with the styling already done, theme everything from one token layer, get blocks and charts in the bargain, and have a path to ship that same UI to mobile as a hybrid native + WebView app, Vireya is the layer above worth adopting, provided you're comfortable with a younger project.

Still deciding? Read why teams choose Vireya, see how theming works, or browse the live blocks and charts showcases. You can also see other comparisons, browse UI library alternatives and the best library by use case, or read about Radix UI directly.

Frequently asked questions

Is Vireya an alternative to Radix UI?

It depends on what you want. Radix gives you unstyled, accessible primitives to style yourself; Vireya gives you finished, styled components — and it builds on Radix (plus base-ui) underneath. If you want to ship styled components without authoring the visual layer, Vireya is the alternative; if you want raw primitives for a bespoke design system, use Radix directly.

Does Vireya use Radix?

Yes. Vireya builds its components on Radix and base-ui primitives for accessible behaviour, focus management and keyboard handling, then adds styling via --v-* tokens plus pre-composed blocks and a charts library. The accessibility you'd get from wiring up Radix yourself is already inside Vireya's components.

Do I still have to write CSS with Vireya like I do with Radix Primitives?

No. Radix Primitives are unstyled, so you author the CSS for every component. Vireya ships static CSS Modules driven by --v-* tokens — you re-theme by changing token values via createTheme(), not by writing component styles from scratch.

How is Vireya different from Radix Themes?

Radix Themes is a styled component set on top of Radix Primitives, configured through accent, gray, radius and scaling presets. Vireya is also styled, but it themes through a broader --v-* token engine with tier-based palettes and runtime switching, and it adds blocks, charts and a hybrid mobile delivery path (web UI in a native WebView with a typed bridge) that Radix Themes does not cover.

Can Vireya reach mobile where Radix can't?

Radix renders to the DOM and is web-only. Vireya layers a hybrid delivery model on top of the same kind of primitives: the web UI runs inside a native WebView shell with a typed bridge (@vireya/rpc) for native functions — the Mobile Bridge pattern Shopify documented and apps like Mercado Livre and Magazine Luiza use — so the styled, accessible UI you build can ship to mobile without a React Native rewrite. The bridge is maturing, Expo first.

Which should I choose?

Choose Radix if you want behaviour-only primitives to style into your own design system, or you want the most widely adopted accessibility foundation today. Choose Vireya if you want finished, themed components built on those same kinds of primitives, with one token layer driving components, blocks and charts, and a path to ship the same UI as a hybrid mobile app.

More Vireya comparisons