Radix UI Primitives Skill
Radix UI Primitives provides low-level, unstyled React components with built-in accessibility, keyboard navigation, and focus management. Perfect for building design systems and custom UI components.
Quick Start Basic Dialog Example import * as Dialog from "@radix-ui/react-dialog"; import { Cross2Icon } from "@radix-ui/react-icons";
function BasicDialog() {
return (
<div className="dialog-fields">
<input placeholder="Name" defaultValue="John Doe" />
<input placeholder="Username" defaultValue="@johndoe" />
</div>
<div className="dialog-actions">
<Dialog.Close asChild>
<button className="btn-primary">Save changes</button>
</Dialog.Close>
</div>
<Dialog.Close asChild>
<button className="dialog-close" aria-label="Close">
<Cross2Icon />
</button>
</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
); }
Dropdown Menu Example import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import { HamburgerMenuIcon, CheckIcon } from "@radix-ui/react-icons";
function UserMenu() { const [showBookmarks, setShowBookmarks] = React.useState(true);
return (
<DropdownMenu.Portal>
<DropdownMenu.Content className="dropdown-content" sideOffset={5}>
<DropdownMenu.Item className="dropdown-item">
New Tab <div className="shortcut">⌘+T</div>
</DropdownMenu.Item>
<DropdownMenu.Item className="dropdown-item">
New Window <div className="shortcut">⌘+N</div>
</DropdownMenu.Item>
<DropdownMenu.Separator className="dropdown-separator" />
<DropdownMenu.CheckboxItem
className="dropdown-item"
checked={showBookmarks}
onCheckedChange={setShowBookmarks}
>
<DropdownMenu.ItemIndicator className="item-indicator">
<CheckIcon />
</DropdownMenu.ItemIndicator>
Show Bookmarks
</DropdownMenu.CheckboxItem>
<DropdownMenu.Arrow className="dropdown-arrow" />
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
); }
Common Patterns Primitive Components
Radix provides 30+ primitive components for common UI patterns:
// Accordion with animation import * as Accordion from "@radix-ui/react-accordion";
function FAQAccordion() {
return (
// Tooltip with delay import * as Tooltip from "@radix-ui/react-tooltip";
function TooltipExample() {
return (
Accessibility Features
Radix automatically handles accessibility:
// All components include proper ARIA attributes // Focus management is handled automatically // Keyboard navigation works out of the box // Screen reader support is built-in
// Example: Select with proper labeling import * as Select from "@radix-ui/react-select";
function AccessibleSelect() {
return (
<Select.Portal>
<Select.Content>
<Select.Viewport>
<Select.Group>
<Select.Label>Fruits</Select.Label>
<Select.Item value="apple">
<Select.ItemText>Apple</Select.ItemText>
<Select.ItemIndicator>
<CheckIcon />
</Select.ItemIndicator>
</Select.Item>
</Select.Group>
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
); }
Composition with asChild
Compose Radix primitives with your own components:
// Use your existing button styles import { Dialog, Tooltip } from "@radix-ui/react-dialog"; import { Button } from "./your-design-system";
function ComposedDialog() {
return (
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.Close asChild>
<Button variant="secondary">Close</Button>
</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
); }
// Multiple primitives on one element
function TooltipDialogButton() {
return (
{/* Dialog content */}
</Dialog.Root>
); }
Custom Component Abstractions
Create your own simplified APIs:
// Custom Dialog wrapper import * as DialogPrimitive from "@radix-ui/react-dialog";
export const CustomDialog = ({ children, trigger, title }) => {
return (
// Usage
;
Styling with Data Attributes
Style components based on their state:
/ Accordion animations / .accordion-content[data-state="open"] { animation: slideDown 300ms ease-out; }
.accordion-content[data-state="closed"] { animation: slideUp 300ms ease-out; }
/ Dropdown positioning / .dropdown-content { transform-origin: var(--radix-dropdown-menu-content-transform-origin); }
.dropdown-content[data-side="top"] { animation: slideUp 0.3s ease-out; }
.dropdown-content[data-side="bottom"] { animation: slideDown 0.3s ease-out; }
/ Focus states / .dropdown-item[data-highlighted] { background: #f0f0f0; }
.dropdown-item[data-state="checked"] { background: #e0e0e0; }
Advanced Patterns // Controlled components for async operations function AsyncDialog() { const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => { e.preventDefault(); setLoading(true);
await submitForm();
setLoading(false);
setOpen(false);
};
return (
// Popover with collision detection
function SmartPopover() {
return (