Rob Austin avatar

Rob Austin - Sep 10, 2026

React Aria Support for Shadcn Blocks (Beta)

Shadcnblocks now supports React Aria as a third primitive library, next to Radix UI and Base UI. Set an aria-* style in components.json and the shadcn CLI installs the React Aria version of every block, in whichever of the eight visual styles you use.

We’re shipping it with a Beta label. This post explains what that label means, why it’s there, and why you shouldn’t let it stop you.

Why React Aria?

React Aria Components is Adobe’s library of unstyled, accessible components. It’s been around longer than either Radix or Base UI, it’s used across Adobe’s own products, and it takes accessibility more seriously than anything else in the ecosystem: consistent press handling across mouse, touch and keyboard, proper collection semantics, internationalised dates and numbers, and screen reader behaviour that has been tested rather than assumed.

shadcn/ui added a React Aria preset of its wrappers, so a Button, Dialog or Select in your project can be backed by react-aria-components instead of Radix. That covers the wrappers. It doesn’t cover the blocks built on top of them, which is where we come in.

How it works

Same mechanism as Base UI. The style in your components.json picks the library and the visual style, and the {style} placeholder in the registry URL sends that choice to us:

{  "$schema": "https://ui.shadcn.com/schema.json",  "style": "aria-vega",  "registries": {    "@shadcnblocks": "https://www.shadcnblocks.com/r/{style}/{name}"  }}

With that in place, npx shadcn@latest add @shadcnblocks/hero1 requests /r/aria-vega/hero1 and gets the React Aria build of hero1. The block id is the same for all three libraries, so nothing in your install commands changes when you switch. All eight styles are available: aria-vega, aria-nova, aria-maia, aria-lyra, aria-mira, aria-luma, aria-sera and aria-rhea.

On the site, the library switcher in the block toolbar (and in the Customize sheet) lets you preview any block with React Aria and open the Code tab to see the React Aria source. The Diff view shows exactly what changed against the Radix version.

So why beta?

Two honest reasons, both about code we had to write ourselves.

1. shadcn’s React Aria preset is missing some wrappers

shadcn’s React Aria registry doesn’t ship a navigation-menu, a menubar or a form. A lot of our navbars use navigation-menu, and plenty of dashboard and form blocks use form. We didn’t want to drop those blocks from React Aria, and we didn’t want to rewrite them without the wrapper, so we wrote the wrappers.

They live in our registry as @shadcnblocks/ui-extras/navigation-menu, @shadcnblocks/ui-extras/menubar and @shadcnblocks/ui-extras/form. Each one is a React Aria implementation that exposes the same export names as its Radix counterpart (NavigationMenu, NavigationMenuTrigger, NavigationMenuContent, Menubar, MenubarItem, Form, FormField, FormMessage, and so on), styled per visual style, and installs into components/ui like any other shadcn component. When a block depends on one, the CLI installs it automatically as a registry dependency. You can also add them directly.

These are shims. They’re solid, they’re typechecked, and they’re used by hundreds of blocks in our own previews. But they’re maintained by us rather than by shadcn, and if shadcn ships official versions we’ll switch to those and retire ours. Until then, they’re the piece of the React Aria path that’s newest and most likely to change.

2. Some third-party components have no React Aria build

A number of our blocks use components from Kibo UI. Kibo doesn’t publish React Aria variants, so for those we maintain our own React Aria builds and serve them from our registry at /r/aria/kibo-ui/{name}. Your block still imports @/components/kibo-ui/…; the CLI just gets that file from us instead of from Kibo when your style is aria-*.

Same story: these work, but they’re ports we maintain rather than the upstream code, and they’ll be revised as we go.

What beta does not mean

It doesn’t mean incomplete. Every block, component, example and page resolves for React Aria. Where a block is plain markup and Tailwind, the React Aria version is the same file as the Radix one. Where a block depends on primitive APIs that differ, we ship a React Aria-specific version, typechecked against the React Aria wrappers, and that’s over 1,600 blocks and examples today.

It doesn’t mean unstable for your project. The code you install is yours, and it doesn’t phone home. If we change a shim next month, your copy keeps working until you choose to --overwrite it.

It doesn’t mean unsupported. Bugs in a React Aria block are bugs and we fix them. If something looks off after switching, re-install the specific block and if it’s still wrong, tell us.

What it does mean: the Radix and Base UI paths have had more months of use behind them, and the React Aria path includes code that only exists because we wrote it. We’d rather say that plainly than pretend the three are equally seasoned.

What changes in your code

The React Aria versions are real ports, not renamed props. If you’ve used React Aria before you’ll recognise the patterns: onPress instead of onClick, isDisabled / isSelected / isOpen instead of disabled / checked / open, id instead of value on collection items, data-selected / data-expanded instead of data-[state=…], and <LinkButton href> where Radix used <Button asChild><a>. Overlays like Tooltip and Popover put the trigger in charge of open state. The React Aria docs page walks through each of these with side-by-side examples.

Getting started

  1. Set "style": "aria-vega" (or another aria-* style) in components.json and make sure your @shadcnblocks registry URL contains {style}.
  2. Reinstall the shadcn/ui wrappers for React Aria: npx shadcn@latest add --all --overwrite.
  3. Install blocks as usual: npx shadcn@latest add @shadcnblocks/hero1.

The CLI installs the block, the React Aria wrappers it needs, any ui-extras shims, react-aria-components, and any other npm dependencies.

When does it leave beta?

When the shims have been in the wild long enough that we stop changing them, or shadcn ships official React Aria versions and we can delete ours. We’ll drop the label when that happens and note it in the changelog.

Docs