smithery.ai

radix-ui

Build accessible, unstyled React UI components with Radix Primitives

First seen Mar 8, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 10,052 B
  • docs SUMMARY.md 84 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 9 installs

SKILL.md

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 (
    <Dialog.Root>
      <Dialog.Trigger asChild>
        <button className="btn-primary">Edit profile</button>
      </Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Overlay className="dialog-overlay" />
        <Dialog.Content className="dialog-content">
          <Dialog.Title className="dialog-title">Edit profile</Dialog.Title>
          <Dialog.Description className="dialog-description">
            Make changes to your profile here.
          </Dialog.Description>

          <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.Root>
      <DropdownMenu.Trigger asChild>
        <button className="icon-btn" aria-label="Menu">
          <HamburgerMenuIcon />
        </button>
      </DropdownMenu.Trigger>

      <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 (
    <Accordion.Root type="single" collapsible className="accordion">
      <Accordion.Item value="item-1" className="accordion-item">
        <Accordion.Header>
          <Accordion.Trigger className="accordion-trigger">
            Is it accessible?
            <ChevronDownIcon className="accordion-chevron" />
          </Accordion.Trigger>
        </Accordion.Header>
        <Accordion.Content className="accordion-content">
          Yes. It adheres to WAI-ARIA design patterns.
        </Accordion.Content>
      </Accordion.Item>
    </Accordion.Root>
  );
}

// Tooltip with delay
import * as Tooltip from "@radix-ui/react-tooltip";

function TooltipExample() {
  return (
    <Tooltip.Provider delayDuration={800}>
      <Tooltip.Root>
        <Tooltip.Trigger asChild>
          <button className="icon-btn">
            <InfoIcon />
          </button>
        </Tooltip.Trigger>
        <Tooltip.Portal>
          <Tooltip.Content className="tooltip" sideOffset={5}>
            Additional information
            <Tooltip.Arrow className="tooltip-arrow" />
          </Tooltip.Content>
        </Tooltip.Portal>
      </Tooltip.Root>
    </Tooltip.Provider>
  );
}

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.Root>
      <Select.Trigger aria-label="Select a fruit">
        <Select.Value placeholder="Choose a fruit…" />
        <Select.Icon>
          <ChevronDownIcon />
        </Select.Icon>
      </Select.Trigger>

      <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.Root>
      <Dialog.Trigger asChild>
        <Button variant="primary">Open Dialog</Button>
      </Dialog.Trigger>

      <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.Root>
      <Tooltip.Root>
        <Tooltip.Trigger asChild>
          <Dialog.Trigger asChild>
            <Button variant="primary">Open Dialog</Button>
          </Dialog.Trigger>
        </Tooltip.Trigger>
        <Tooltip.Portal>
          <Tooltip.Content>Opens a modal dialog</Tooltip.Content>
        </Tooltip.Portal>
      </Tooltip.Root>

      {/* 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 (
    <DialogPrimitive.Root>
      <DialogPrimitive.Trigger asChild>{trigger}</DialogPrimitive.Trigger>
      <DialogPrimitive.Portal>
        <DialogPrimitive.Overlay className="overlay" />
        <DialogPrimitive.Content className="content">
          <DialogPrimitive.Title>{title}</DialogPrimitive.Title>
          {children}
          <DialogPrimitive.Close asChild>
            <button className="close-btn">×</button>
          </DialogPrimitive.Close>
        </DialogPrimitive.Content>
      </DialogPrimitive.Portal>
    </DialogPrimitive.Root>
  );
};

// Usage
<CustomDialog title="Settings" trigger={<Button>Open Settings</Button>}>
  <div>Settings content here</div>
</CustomDialog>;

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 (
    <Dialog.Root open={open} onOpenChange={setOpen}>
      <Dialog.Trigger asChild>
        <Button>Open Form</Button>
      </Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Content>
          <form onSubmit={handleSubmit}>
            <input name="email" type="email" required />
            <Button type="submit" disabled={loading}>
              {loading ? "Submitting…" : "Submit"}
            </Button>
          </form>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}

// Popover with collision detection
function SmartPopover() {
  return (
    <Popover.Root>
      <Popover.Trigger asChild>
        <Button>Click me</Button>
      </Popover.Trigger>
      <Popover.Portal>
        <Popover.Content
          className="popover"
          sideOffset={10}
          collisionPadding={20}
        >
          Content that avoids screen edges
          <Popover.Arrow className="popover-arrow" />
        </Popover.Content>
      </Popover.Portal>
    </Popover.Root>
  );
}