Drawer
在保留页面上下文时展示扩展任务。中文惯用名:抽屉。
稳定本期新增已接入
元信息
| 字段 | 值 |
|---|---|
| 规范 ID | component.drawer |
| 名称 | Drawer |
| 二级分类 | 反馈(feedback) |
| 用途 | 在保留页面上下文时展示扩展任务 |
| 描述 | 中文惯用名:抽屉。 |
预览
静态结构:经 vaul 原语渲染——根节点为受控 Drawer(open 缺省按 false 处理),弹层经 Portal 挂到 body:遮罩(data-slot="drawer-overlay",fixed inset-0 z-50、半透明覆盖色)+ 抽屉面板(data-slot="drawer-content",fixed z-50、bg-popover,按 placement 映射 vaul direction 定位:right / left 贴边全高、宽 3/4 且 sm 以上最大 sm,top / bottom 贴边全宽、max-h-[80vh]),bottom 方向额外渲染顶部拖拽把手(h-2 圆条);title 提供时渲染头部(data-slot="drawer-header" > data-slot="drawer-title"),其后为内容容器(flex-1 overflow-auto p-4)承载 children。遮罩 / Escape / 拖拽关闭经 onOpenChange(false) 触发 onClose。
DSL 结构
{
"type": "Drawer",
"props": {
"open": true,
"title": "订单详情",
"placement": "right"
},
"events": {
"onClose": {
"action": "setState",
"params": {
"drawerOpen": false
}
}
},
"children": [
{
"type": "Text",
"props": {
"text": "抽屉内容:订单号、金额、收货地址等详情字段。"
}
}
]
}何时用
何时使用
- 在保留页面上下文的同时展示扩展任务:查看 / 编辑详情、填写较长的表单、批量操作的参数面板。
- 内容量大需要纵向滚动,或希望用户仍能瞥见背后的列表。
- 需要从固定方向滑出的面板:右侧(默认)详情表单、左侧导航 / 目录、上下次要面板。
何时不用
- 必须阻断当前流程、确认后才能继续的操作:使用 Dialog(居中模态,注意力更集中)。
- 只需就近的轻量确认:使用 Popconfirm;只需上下文补充内容:使用 Popover。
- 页面级常驻的导航 / 目录:使用布局组件,Drawer 是临时面板。
变体
| 变体 | 视觉形态 | 适用场景 |
|---|---|---|
| right 右侧(默认) | 右侧贴边全高滑出,宽 3/4(sm 以上最大 sm) | 详情查看、编辑表单等最常见用法 |
| left 左侧 | 左侧贴边全高滑出 | 导航、目录、过滤器面板 |
| top 顶部 | 顶部贴边全宽滑出,max-h-[80vh] | 顶部工具面板、全局筛选 |
| bottom 底部 | 底部贴边全宽滑出、max-h-[80vh]、带拖拽把手 | 移动端友好(可拖拽关闭)、快捷操作面板 |
| 仅标题 / 无标题 | title 缺省时不渲染头部,内容直接铺满 | 内容自带标题或纯容器场景 |
API 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | — | 抽屉标题,渲染为 DrawerTitle;缺省时不渲染头部 |
open | boolean | false | 受控开关(可绑 ${state.x} 表达式);缺省按 false 处理,组件无 trigger 属性 |
placement | `'left' | 'right' | 'top' |
onClose | () => void | — | 关闭事件(遮罩 / Escape / 拖拽关闭时触发,仅关闭回调;Renderer 绑定 events.onClose) |
children | ReactNode | — | 内容(DSL 子树,经 Renderer children 机制渲染,置于 flex-1 overflow-auto p-4 容器内) |
className / style | string / CSSProperties | — | 通用:抽屉内容根节点 class 合并 / 内联样式 |
使用规范
- Drawer 无 trigger 属性:始终受控,open 绑状态表达式并在 onClose 写回 false,否则用户关不掉。
- 方向按任务选:详情 / 表单用 right(默认,符合阅读与操作顺序),导航用 left,移动端次要面板用 bottom。
- 内容容器已自带滚动(flex-1 overflow-auto):长表单直接纵向排布,不要再嵌套滚动容器。
- 抽屉宽度固定(right / left 为 3/4、sm 以上最大 sm):放不下的宽表改用整页路由或 Dialog 承载。
- 与 Dialog 的分工:需要用户停下来先处理完用 Dialog;边看列表边补详情用 Drawer。
正例
- ✓ 列表行「查看详情」:placement=right、title 为对象名,内容纵向排布字段说明。
- ✓ 后台配置面板:placement=left 放导航与过滤器,不遮挡主内容区。
- ✓ 移动端快捷操作:placement=bottom(带拖拽把手),下滑即可关闭。
反例
- ✕ 用 Drawer 承载必须立即处理的确认(应使用 Dialog,居中模态更能拉回注意力)。
- ✕ 声明了 open 却不处理 onClose,抽屉只能靠刷新页面消失。
- ✕ 在抽屉内再嵌入抽屉或 Dialog 做多层叠加(层级混乱,应先关闭再进入)。
Design Token 映射
不适用:组件 tokenRefs 为空:样式 Token 数据尚未接入,三层映射(Primitive → Semantic → Component)待样式 Token 接入后回填。