开放组合
Radix Primitives 被设计为可以按你的需要改造。开放的组件架构给了你对每一个部件的细粒度访问权,你可以把它们包裹起来,加上自己的事件监听、props 或 ref。
部件是公开的
一个组件不是黑盒。以 Dialog 为例,你手上真正拿到的是这些具名部件:
Dialog.RootDialog.TriggerDialog.PortalDialog.OverlayDialog.ContentDialog.TitleDialog.DescriptionDialog.Close
它们的清单不是写在文档里就算数,而是各包真实导出的名字:组件索引里的部件列表由脚本从包的 export 语句中抽取。
asChild
多数渲染 DOM 的部件接受 asChild。传了之后,组件会跳过自己渲染的那一层元素,把自己的 props 合并到你给的子元素上;纯逻辑部件(例如 Dialog.Portal)则没有这个属性。
import { Dialog } from 'radix-ui';
// 触发器渲染成 <a> 而不是 <button>
<Dialog.Trigger asChild>
<a href="/settings">前往设置</a>
</Dialog.Trigger>
底层的实现是 Slot 原语:props 合并到已有元素上,其余的 ref 与事件也一并接过去。
包裹你自己的组件
因为部件是公开的,你可以写一层自己的封装,之后整个项目都用自己的那层:
import type { ComponentProps } from 'react';
import { Dialog } from 'radix-ui';
type DialogProps = ComponentProps<typeof Dialog.Root>;
function DialogShell({ children, ...props }: DialogProps) {
return (
<Dialog.Root {...props}>
<Dialog.Portal>
<Dialog.Overlay className="backdrop" />
<Dialog.Content className="sheet">{children}</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}
不需要 fork 源码,也不需要在组件外层再包一个 div 来监听事件。
这一页涉及到的组件
Switch
Toggle
Checkbox
RadioGroup
Progress
Separator
Accordion
内容区域。
ScrollArea
Slider
Popover
Tooltip
Progress
Switch
打开后焦点被锁在对话框内,按 Esc 关闭。