radix-ui
📒 @radix-ui 的作用和使用方式。
@radix-ui 是一套无样式的 React UI 组件原语。
“无样式”是它最重要的特点:它不负责让组件变得好看,而是负责让组件“行为正确”。比如弹窗怎么打开关闭、键盘怎么操作、焦点怎么管理、屏幕阅读器怎么识别,这些复杂但很容易被忽略的细节,Radix UI 会帮你处理。
它解决什么问题
有些组件看起来简单,实际很容易写错。
比如 Dialog 弹窗:
- 打开弹窗后,键盘焦点应该进入弹窗。
- 按
Esc应该能关闭。 - 弹窗打开时,背景内容不应该被误操作。
- 屏幕阅读器需要知道这是一个弹窗。
- 关闭后,焦点最好回到打开弹窗的按钮上。
再比如 Dropdown Menu:
- 鼠标可以点击。
- 键盘方向键可以移动。
Enter可以选择。- 点击外部区域可以关闭。
- 菜单定位不能乱飘。
这些都不是纯 CSS 能解决的。Radix UI 的作用就是把这些交互行为封装好,让开发者专心写业务和样式。
它具体做什么
Radix UI 提供很多底层组件,例如:
@radix-ui/react-dialog:弹窗。@radix-ui/react-dropdown-menu:下拉菜单。@radix-ui/react-popover:浮层。@radix-ui/react-tabs:标签页。@radix-ui/react-tooltip:提示气泡。@radix-ui/react-select:选择器。@radix-ui/react-switch:开关。
它们通常只提供结构和行为,不提供固定视觉风格。
也就是说,你拿到的是一个“会正确工作的组件骨架”,至于长什么样,由你用 Tailwind CSS、CSS Modules、普通 CSS 或其他方案来写。
基本使用方式
安装某个组件包:
npm install @radix-ui/react-dialog使用 Dialog:
import * as Dialog from "@radix-ui/react-dialog";
export function DeleteDialog() {
return (
<Dialog.Root>
<Dialog.Trigger>删除</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 bg-black/40" />
<Dialog.Content className="fixed left-1/2 top-1/2 w-96 -translate-x-1/2 -translate-y-1/2 rounded-md bg-white p-6">
<Dialog.Title>确认删除?</Dialog.Title>
<Dialog.Description>
删除后数据将无法恢复。
</Dialog.Description>
<Dialog.Close>取消</Dialog.Close>
<button>确认删除</button>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}这段代码里:
Dialog.Root:管理整个弹窗状态。Dialog.Trigger:触发打开弹窗的元素。Dialog.Portal:把弹窗渲染到页面顶层,避免被父元素遮挡。Dialog.Overlay:背景遮罩。Dialog.Content:弹窗主体内容。Dialog.Title/Dialog.Description:提供语义和无障碍信息。Dialog.Close:关闭弹窗。
和 shadcn/ui 的关系
很多 shadcn/ui 组件底层都用了 Radix UI。
可以这样理解:
- Radix UI:提供交互能力和无障碍能力。
- shadcn/ui:把 Radix UI、Tailwind CSS 和项目组件组织方式包装成一套更好用的组件代码。
比如 shadcn/ui 的 Dialog 组件,底层通常就是基于 @radix-ui/react-dialog 封装的。
你平时开发时,不一定会直接写 Radix UI 原始组件。很多时候你会先用 shadcn/ui 提供的封装版本;只有当你要做高度自定义交互时,才直接使用 Radix UI。
什么时候直接用 Radix UI
适合:
- 需要自己设计 UI 样式,但不想从零写复杂交互。
- 项目有自己的设计系统。
- 需要高度自定义弹窗、菜单、浮层、选择器等组件。
- 希望组件支持键盘操作和无障碍体验。
不太适合:
- 想要开箱即用的完整视觉组件库。
- 不想自己写样式。
- 非 React 项目。
使用建议
如果项目已经使用 shadcn/ui,优先使用 components/ui 里封装好的组件。
只有这些场景再直接使用 Radix UI:
- shadcn/ui 没有提供对应组件。
- 现有组件封装不满足业务需求。
- 需要做一个项目自己的基础组件。
直接使用 Radix UI 时,建议把它再封装一层,放到项目的基础组件目录里,而不是在业务页面到处直接写 Radix UI 结构。
总结
@radix-ui 是 React 生态里非常适合做底层 UI 交互的组件原语。它不负责样式,但负责弹窗、菜单、浮层这类组件最难写对的行为细节;如果说 shadcn/ui 是“能直接用的组件源码”,Radix UI 就是这些复杂组件背后的交互发动机。