Drawer
从屏幕边缘滑入的侧边面板组件
抽屉(Drawer)从屏幕边缘滑入,用于在不离开当前页面的情况下展示辅助内容或操作面板。基于 Dialog 封装,继承标题、描述、页脚、关闭按钮等完整能力,并新增方向控制和内容滚动功能。
import { Drawer, DrawerContent, type DrawerSide } from '@skyroc/web-ui';何时使用
- 需要在不离开当前页面的情况下查看详情、编辑表单或完成一段辅助流程。
- 需要从页面边缘展开筛选、目录、购物车、产品配置等面板。
- 与 Dialog 的区分:Dialog 居中弹出,适合短确认和聚焦任务;Drawer 从边缘进入,更适合保留页面上下文。
- 与 BottomSheet 的区分:BottomSheet 更偏移动端底部手势;Drawer 支持四个方向,适合响应式页面和桌面侧边面板。
基础用法
通过 trigger 提供触发元素,通过 title、description 和 children 组织面板内容。默认从右侧滑入,并渲染一个 OK 页脚按钮。
<Drawer
title="产品配置"
description="调整当前产品的展示参数"
trigger={<Button>打开配置</Button>}
>
<div>Drawer Content</div>
</Drawer>方向
通过 contentProps.side 控制 Drawer 的滑入方向,默认为 right:
| 方向 | 说明 | 适用场景 |
|---|---|---|
right | 从右侧滑入 | 详情面板、属性编辑 |
left | 从左侧滑入 | 导航目录、筛选面板 |
top | 从顶部滑入 | 搜索、通知、全局提示 |
bottom | 从底部滑入 | 快捷操作、移动端入口 |
左右方向的 Drawer 默认宽度为 w-3/4,在 sm 断点以上限制为 max-w-sm;上下方向的 Drawer 占满水平宽度。
const sides: DrawerSide[] = ['left', 'right', 'top', 'bottom'];
{sides.map(side => (
<Drawer
key={side}
title="Drawer Title"
trigger={<Button>{side}</Button>}
contentProps={{ side }}
>
Drawer Content
</Drawer>
))}可滚动内容
scrollable 控制内容区是否可滚动,默认为 true。当内容超出面板高度时自动出现滚动条。设为 false 则内容区不滚动,适合内容高度固定的场景。
<Drawer
title="长内容"
trigger={<Button>打开</Button>}
>
{Array.from({ length: 100 }).map((_, index) => (
<div key={index}>Drawer Content</div>
))}
</Drawer>标题、描述和页脚
Drawer 继承 Dialog 的标题、描述、关闭按钮和页脚能力:
title渲染面板标题,用于说明当前面板目的。description渲染标题下方的补充说明。footer控制底部操作区。titleProps、descriptionProps、headerProps、footerProps可向对应结构传入额外属性。
页脚规则与 Dialog 保持一致:
- 默认显示 OK 按钮,文本可通过
okText自定义,点击回调为onOk。 - 传入 ReactNode 可完全替换页脚内容。
- 传入
null或false隐藏页脚。
尺寸和样式
通过 size 调整面板标题、描述、页脚和内容区域的字号与间距。通过 classNames 可分别控制 overlay、content、header、title、description、footer 和 close。
需要改变面板宽度或高度时,优先通过 className 或 contentProps.className 覆盖内容容器:
<Drawer
title="宽面板"
trigger={<Button>打开</Button>}
className="sm:max-w-xl"
>
Drawer Content
</Drawer>受控状态
Drawer 透传 Radix Dialog Root 的 open、defaultOpen、onOpenChange 和 modal。当打开状态需要和路由、表单流程或异步任务联动时,使用受控模式。
API
Drawer
基于 Dialog 封装,继承 Dialog 的标题、描述、页脚、关闭按钮、受控状态和 slot 样式能力。以下列出 Drawer 特有属性及常用的 Dialog 继承属性。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| scrollable | 内容区是否可滚动 | boolean | true |
| trigger* | 触发打开的元素 | ReactNode | - |
| children | 内容区节点,显示在头部和页脚之间;内容会被可滚动容器包裹 | ReactNode | - |
| title | 标题文本 | ReactNode | - |
| description | 描述文本,显示在标题下方 | ReactNode | - |
| footer | 页脚内容;默认渲染 OK 按钮,传入 null 或 false 隐藏页脚 | ReactNode | null | false | - |
| open | 受控模式下的打开状态 | boolean | - |
| onOpenChange | 打开/关闭状态变化回调 | (open: boolean) => void | - |
| defaultOpen | 非受控模式下的初始打开状态 | boolean | - |
| modal | 是否以模态模式打开(显示遮罩层) | boolean | true |
| size | 尺寸,影响内容面板及标题、描述、页脚等子组件的字号与间距 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'md' |
| className | 传递给内容容器的自定义 class;优先级高于 classNames.content | ClassValue | - |
| classNames | 各 slot 的自定义 class | DrawerClassNames | - |
| contentProps | 传递给 DrawerContent 的额外属性,可通过 side 控制滑入方向 | DrawerContentProps | - |
| onOk | OK 按钮点击回调 | (e: React.MouseEvent<HTMLButtonElement>) => void | - |
| okText | OK 按钮文本 | ReactNode | 'OK' |
| okButtonProps | OK 按钮的额外属性 | ButtonProps | - |
| overlayProps | 传递给遮罩层的额外属性 | DialogOverlayProps | - |
| closeProps | 传递给关闭按钮的额外属性 | DialogCloseProps | - |
| headerProps | 传递给头部容器的额外属性 | DialogHeaderProps | - |
| footerProps | 传递给页脚容器的额外属性 | DialogFooterProps | - |
| titleProps | 传递给标题组件的额外属性 | DialogTitleProps | - |
| descriptionProps | 传递给描述组件的额外属性 | DialogDescriptionProps | - |
DrawerContent
通过 contentProps 传递给内容容器的属性,控制滑入方向和样式。继承 Radix Dialog Content 的所有属性。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| side | 滑入方向 | 'top' | 'right' | 'bottom' | 'left' | 'right' |
| className | 内容容器的 class | ClassValue | - |
类型
DrawerClassNames
各 slot 的自定义 class,复用 Dialog 的 slot 结构。
| 字段 | 类型 | 说明 |
|---|---|---|
| overlay | ClassValue | 遮罩层的 class。 |
| content | ClassValue | 内容容器的 class。 |
| header | ClassValue | 头部的 class。 |
| title | ClassValue | 标题的 class。 |
| description | ClassValue | 描述文本的 class。 |
| footer | ClassValue | 页脚的 class。 |
| close | ClassValue | 关闭按钮的 class。 |
DrawerContentProps
内容容器属性,继承 Radix Dialog Content 的定位、焦点管理等属性。
| 字段 | 类型 | 说明 |
|---|---|---|
| side | 'top' | 'right' | 'bottom' | 'left' | 滑入方向。 |
| className | ClassValue | 自定义 class。 |
| onOpenAutoFocus | (event: Event) => void | 打开时自动聚焦的回调。 |
| onCloseAutoFocus | (event: Event) => void | 关闭时自动聚焦的回调。 |
| onEscapeKeyDown | (event: KeyboardEvent) => void | 按下 Escape 键的回调。 |
| onPointerDownOutside | (event: PointerDownOutsideEvent) => void | 在内容区外点击的回调。 |
| onInteractOutside | (event: Event) => void | 在内容区外交互的回调。 |
DialogOverlayProps
遮罩层属性,继承 Radix Dialog Overlay 的所有属性。
| 字段 | 类型 | 说明 |
|---|---|---|
| className | ClassValue | 自定义 class。 |
| forceMount | boolean | 强制挂载(即使关闭状态也渲染 DOM)。 |