UI Design System
build dev

Drawer

在保留页面上下文时展示扩展任务。中文惯用名:抽屉。
稳定本期新增已接入

元信息

字段值
规范 IDcomponent.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 结构

DslNode
{
  "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 属性

属性类型默认值说明
titlestring—抽屉标题,渲染为 DrawerTitle;缺省时不渲染头部
openbooleanfalse受控开关(可绑 ${state.x} 表达式);缺省按 false 处理,组件无 trigger 属性
placement`'left''right''top'
onClose() => void—关闭事件(遮罩 / Escape / 拖拽关闭时触发,仅关闭回调;Renderer 绑定 events.onClose)
childrenReactNode—内容(DSL 子树,经 Renderer children 机制渲染,置于 flex-1 overflow-auto p-4 容器内)
className / stylestring / 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 接入后回填。