重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
radix-ui by slanycukr/riot-api-project
npx skills add https://github.com/slanycukr/riot-api-project --skill radix-uiRadix UI Primitives 提供低层级、无样式的 React 组件,内置无障碍访问、键盘导航和焦点管理功能。非常适合构建设计系统和自定义 UI 组件。
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>
);
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
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>
);
}
Radix 为常见 UI 模式提供 30 多个基础组件:
// 带动画的折叠面板
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>
);
}
// 带延迟的工具提示
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>
);
}
Radix 自动处理无障碍访问:
// 所有组件都包含适当的 ARIA 属性
// 焦点管理自动处理
// 键盘导航开箱即用
// 内置屏幕阅读器支持
// 示例:带有适当标签的选择器
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>
);
}
将 Radix 基础组件与你自己的组件组合:
// 使用你现有的按钮样式
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>
);
}
// 在单个元素上使用多个基础组件
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>
);
}
创建你自己的简化 API:
// 自定义对话框包装器
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>
);
};
// 用法
<CustomDialog title="Settings" trigger={<Button>Open Settings</Button>}>
<div>Settings content here</div>
</CustomDialog>;
根据组件状态设置样式:
/* 折叠面板动画 */
.accordion-content[data-state="open"] {
animation: slideDown 300ms ease-out;
}
.accordion-content[data-state="closed"] {
animation: slideUp 300ms ease-out;
}
/* 下拉菜单定位 */
.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;
}
/* 焦点状态 */
.dropdown-item[data-highlighted] {
background: #f0f0f0;
}
.dropdown-item[data-state="checked"] {
background: #e0e0e0;
}
// 用于异步操作的可控组件
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>
);
}
// 带碰撞检测的弹出框
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>
);
}
每周安装量
46
代码仓库
GitHub 星标数
2
首次出现
2026年1月24日
安全审计
已安装于
github-copilot30
codex29
opencode29
claude-code29
gemini-cli27
cursor22
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.
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>;
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;
}
// 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>
);
}
Weekly Installs
46
Repository
GitHub Stars
2
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
github-copilot30
codex29
opencode29
claude-code29
gemini-cli27
cursor22
前端设计系统技能:生产级UI设计、设计令牌与可访问性指南
8,500 周安装