React Aria
shadcn/ui
Shadcnblocks

Shadcn Blocks + React Aria

Beta

Every Shadcnblocks block, component and page is available for Adobe's React Aria Components, alongside Radix UI and Base UI. Same blocks, accessibility-first primitives underneath.

Accessibility-First Primitives

React Aria Components is Adobe's library of unstyled, accessible components: consistent press handling across mouse, touch and keyboard, collection semantics, internationalised dates and numbers, and screen reader behaviour that has been tested rather than assumed. Same shadcn/ui wrappers, same blocks.

Radix UI

The established choice

  • Battle-tested in production
  • Extensive component library
  • Large community ecosystem
style: "radix-vega"

React Aria

Accessibility and internationalisation first

  • Adaptive press, hover and focus across every input
  • Tested against real screen readers and devices
  • Over 30 locales, 13 calendar systems, RTL layout
style: "aria-vega"
Radix UI
← Drag to compare →
React Aria
components/ui/tooltip.tsx
"use client"

import { cn } from "cn"
import * as React from "react"
import { Tooltip as TooltipPrimitive } from "radix-ui"

function TooltipProvider({
  delayDuration = 0,
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
  return (
    <TooltipPrimitive.Provider
      data-slot="tooltip-provider"
      delayDuration={delayDuration}
      {...props}
    />
  )
}

function Tooltip({
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
  return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
}

function TooltipTrigger({
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
  return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}

function TooltipContent({
  className,
  sideOffset = 0,
  children,
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
  return (
    <TooltipPrimitive.Portal>
      <TooltipPrimitive.Content
        data-slot="tooltip-content"
        sideOffset={sideOffset}
        className={cn(
          "data-open:animate-in data-open:fade-in-0...",
          className
        )}
        {...props}
      >
        {children}
        <TooltipPrimitive.Arrow className="..." />
      </TooltipPrimitive.Content>
    </TooltipPrimitive.Portal>
  )
}

export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
components/ui/tooltip.tsx
"use client"

import { cn } from "cn"
import * as React from "react"
import {
  Focusable,
  OverlayArrow,
  Tooltip as TooltipPrimitive,
  TooltipTrigger as TooltipTriggerPrimitive,
} from "react-aria-components"

function TooltipTrigger({
  delay = 0,
  children,
  ...props
}: React.ComponentProps<typeof TooltipTriggerPrimitive>) {
  const [trigger, tooltip] = React.Children.toArray(children)

  return (
    <TooltipTriggerPrimitive
      data-slot="tooltip-trigger"
      delay={delay}
      {...props}
    >
      <Focusable>{trigger}</Focusable>
      {tooltip}
    </TooltipTriggerPrimitive>
  )
}

function Tooltip({
  className,
  placement = "top",
  offset = 4,
  children,
  ...props
}: React.ComponentProps<typeof TooltipPrimitive>) {
  return (
    <TooltipPrimitive
      data-slot="tooltip-content"
      placement={placement}
      offset={offset}
      className={cn(
        "data-entering:animate-in data-entering:fade-in-0...",
        className
      )}
      {...props}
    >
      {children}
      <OverlayArrow className="..." />
    </TooltipPrimitive>
  )
}

export { Tooltip, TooltipTrigger }
Key difference: radix-ui vs react-aria-components
Same styling, different primitives

Why React Aria is in Beta

Every block works with React Aria today. The Beta label is about two pieces of code that only exist because we wrote them.

Wrappers shadcn does not ship

shadcn's React Aria preset has no navigation menu, menubar or form wrapper. Rather than drop those blocks, we ship our own React Aria implementations as @shadcnblocks/ui-extras/*. The CLI installs them into components/ui automatically when a block needs them.

  • ui-extras/navigation-menu

    Used by most navbar blocks. Same exports as the Radix wrapper.

  • ui-extras/menubar

    Dashboard and app-shell blocks. Same exports as the Radix wrapper.

  • ui-extras/form

    Form, FormField, FormMessage and friends for react-hook-form blocks.

Third-party components without a React Aria build

Some blocks use Kibo UI components, and Kibo does not publish React Aria variants. For those we maintain React Aria builds and serve them from our registry. Your block still imports @/components/kibo-ui/…; the CLI simply fetches the file from us.

What beta does not mean

  • Not incomplete: every block, component and page resolves.
  • Not unstable for you: the code you install is yours and keeps working.
  • Not unsupported: bugs in React Aria blocks are bugs we fix.

The label comes off when the shims have settled, or when shadcn ships official versions and we can delete ours. Read the full write-up

Simple Configuration

One setting in your components.json controls both the UI library and visual style. The registry URL's {style} placeholder sends it to us.

components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "aria-vega",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui"
},
"registries": {
"@shadcnblocks": "https://www.shadcnblocks.com/r/{style}/{name}"
}
}
Style
{library}-{style}
Examples
aria-vega, aria-nova, aria-maia, aria-lyra
aria-mira, aria-luma, aria-sera, aria-rhea
Then: reinstall the shadcn/ui wrappers for React Aria with npx shadcn@latest add --all --overwrite and add blocks as usual with npx shadcn@latest add @shadcnblocks/hero1. The CLI installs the block, the React Aria wrappers, any ui-extras shims, and react-aria-components.

Ready to Try React Aria?

Open any block, switch the library to React Aria in the toolbar, and compare the code against Radix in the Diff view.