Radix UI Design System

SkillMedia

Provides Radix UI patterns for building accessible design systems with headless components, theming, and compound component architecture. Use when building UI with Radix UI primitives or when the user mentions Radix UI, headless components, or accessible component libraries.

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the Radix UI Design System skill

About this skill

Software Development Department

What this skill tells your AI

The instructions your AI receives, as published by tranhieutt/software_development_department in .claude/skills/radix-ui-design-system/SKILL.md and read by ahel’s review.

Critical rules (non-obvious)

  • Always use asChild on Trigger/Close — prevents nested <button> inside <button> DOM errors
  • Always include <Dialog.Title> and <Dialog.Description> — screen readers require them; omitting causes a11y violations
  • Never mix controlled + uncontrolled — don't use both defaultValue and value on same component
  • Animations need forceMount — without it Portal unmounts instantly, killing Framer Motion exit animations
  • Dropdown positioning off? — parent has overflow: hidden or CSS transform; always wrap in <Portal>

Core pattern: Dialog

<Dialog.Root open={open} onOpenChange={setOpen}>
  <Dialog.Trigger asChild><button>Open</button></Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay className="overlay" />
    <Dialog.Content className="content">
      <Dialog.Title>Title</Dialog.Title>       {/* required */}
      <Dialog.Description>Desc</Dialog.Description> {/* required */}
      <Dialog.Close asChild><button>Close</button></Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Theming: CSS variables (recommended)

:root { --color-primary: 220 90% 56%; --radius: 0.5rem; }
[data-theme="dark"] { --color-primary: 220 90% 66%; }
<Dialog.Content className="bg-[hsl(var(--color-primary))] rounded-[var(--radius)]" />

Theming: CVA for variants

import { cva } from 'class-variance-authority';
const button = cva("base-styles", {
  variants: {
    variant: { default: "bg-primary", destructive: "bg-red-500" },
    size: { sm: "h-9 px-3", md: "h-10 px-4" },
  },
  defaultVariants: { variant: "default", size: "md" },
});

Animation with Framer Motion

<Dialog.Portal forceMount>           {/* forceMount: critical */}
  <AnimatePresence>
    {open && (
      <Dialog.Overlay asChild>
        <motion.div initial={{opacity:0}} animate={{opacity:1}} exit={{opacity:0}} />
      </Dialog.Overlay>
    )}
  </AnimatePresence>
</Dialog.Portal>

Hook form integration (Select)

<Controller name="country" control={control} render={({ field }) => (
  <Select.Root onValueChange={field.onChange} value={field.value}>
    <Select.Trigger><Select.Value placeholder="Select..." /><Select.Icon /></Select.Trigger>
    <Select.Portal>
      <Select.Content><Select.Viewport>
        <Select.Item value="us"><Select.ItemText>US</Select.ItemText></Select.Item>
      </Select.Viewport></Select.Content>
    </Select.Portal>
  </Select.Root>
)} />

Primitives quick reference

ComponentKey parts
DialogRoot · Trigger · Portal · Overlay · Content · Title · Description · Close
DropdownMenuRoot · Trigger · Portal · Content · Item · Separator · CheckboxItem · RadioGroup · Sub
TabsRoot · List · Trigger · Content
TooltipProvider · Root · Trigger · Portal · Content · Arrow
SelectRoot · Trigger · Value · Icon · Portal · Content · Viewport · Item · ItemText · ItemIndicator

shadcn vs raw Radix

  • shadcn: quick prototyping, standard designs; run npx shadcn@latest add dialog
  • Raw Radix: full customization, unique designs, zero-dependency component library

Signals

GitHub stars
72
Forks
40
Last commit
May 2026

ahel review

  • K5info
    obfuscation

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Item type
skill
Key
radix-ui-design-system-tranhieutt
Source
github.com/tranhieutt/software_development_department