Composition recipes
Practical patterns for combining Rad UI primitives into common product UI. Each recipe names who owns state and the minimum anatomy required for accessible behavior.
Confirm destructive action
Components: AlertDialog
State owner: parent (open / onOpenChange or uncontrolled trigger)
Keep title and description in the content layer so screen readers announce purpose before action buttons.
Settings panel with sections
Components: Tabs + form controls
State owner: Tabs for active section; each field manages its own value
Mount heavy panel content inside the active Tabs.Content only when panels are large.
Command palette
Components: Dialog + Command
State owner: dialog open; command value for selection
Trap focus inside the dialog; return focus to the opener when the palette closes.
Form field with label and error
Components: TextArea or NumberField + your field wrapper
State owner: parent form / field component
Wire htmlFor / id and aria-invalid in your wrapper — Rad UI exposes the primitives, not your validation messaging.
Nested disclosure
Components: Accordion inside Card
State owner: Accordion (type, value, onValueChange)
Use accordion for FAQ-style content inside a card shell. Avoid nesting multiple roving-focus containers (menus inside accordion headers) without testing keyboard order.
Recipe checklist
- Named which component owns open/selected/value state
- Included required title/description parts for modal patterns
- Verified keyboard and focus behavior manually
- Used per-component imports (
@radui/ui/Component)