组件

Drawer

一个 React 抽屉,可从任意边缘滑入,采用 Liquid Glass 表面并支持手势关闭。

Drawer 是贴边滑入的面板。它内部渲染 Portal、遮罩、弹窗、标题、描述、可选正文以及自定义操作区,并支持滑动关闭与可选吸附点。

与居中的 Dialog 不同,Drawer 从屏幕边缘滑入,适合移动端设置面板、筛选条件和侧边导航。

基础示例

默认从底部滑入。open 控制显示,footer 放置自己的按钮;按钮不会自动关闭抽屉,需要像示例一样更新 open。

侧边抽屉

direction 支持四个取值:down 从底部滑入,up 从顶部滑入,left 和 right 从对应侧边滑入。默认 down,组件会同时调整弹窗位置、圆角、进入动画和滑动关闭方向。

手势关闭

触摸设备上可以朝 direction 对应的方向拖动抽屉来关闭;桌面端仍可使用遮罩、Esc 或操作区按钮。

Open the drawer, then swipe it downward on a touch screen.

吸附点

snapPoints、defaultSnapPoint、snapPoint、onSnapPointChange 与 snapToSequentialPoints 用于配置吸附高度,让底部或顶部抽屉在预设高度之间停靠。

禁止遮罩关闭

disablePointerDismissal 会阻止点击遮罩关闭抽屉,Esc 键和操作区按钮仍然可用;适合包含未保存内容的流程。

无障碍

Drawer 使用与 Dialog 相同的对话框语义:焦点移动到面板内,打开期间被限制在面板中,关闭后返回触发器。title 为面板命名,description 提供描述。

Escape、点击背景与滑动手势都会关闭抽屉;关闭可能丢失工作时,请设置 disablePointerDismissal 并提供可见的取消操作。避免让滑动手势与横向滚动内容冲突。浮层焦点规则见可访问性指南。

API 参考

属性类型默认值说明
titleReactNode—抽屉标题,必填。
descriptionReactNode—标题下方的说明文字。
childrenReactNode—描述与操作区之间的正文内容。
footerReactNode—底部操作区,可放置任意数量的控件。
direction"down" | "up" | "left" | "right""down"滑入边缘,同时作为滑动关闭方向。
openboolean—受控的打开状态。
defaultOpenbooleanfalse非受控时的初始打开状态。
onOpenChange(open: boolean, details) => void—抽屉打开或关闭时调用。
onOpenChangeComplete(open: boolean) => void—打开或关闭动画结束后调用。
modalboolean | "trap-focus"true控制焦点锁定与页面滚动锁定。
disablePointerDismissalbooleanfalse禁止点击遮罩关闭。
actionsRefRefObject<Actions | null>—命令式的 close 与 unmount 操作。
handleDrawerHandle—将抽屉与外部触发器关联。
triggerIdstring | null—与抽屉关联的触发器 ID。
defaultTriggerIdstring | null—初始打开时使用的触发器 ID。
snapPointsDrawerSnapPoint[]—吸附高度,可用视口比例、像素数字或 px/rem 字符串表示。
snapToSequentialPointsbooleanfalse根据拖动距离而不是速度选择下一个吸附点。
snapPointDrawerSnapPoint | null—受控的当前吸附点。
defaultSnapPointDrawerSnapPoint | null—非受控时的初始吸附点。
onSnapPointChange(snapPoint: DrawerSnapPoint | null, details) => void—当前吸附点变化时调用。
classNamestring—合并到弹窗的 Tailwind 类名。
styleCSSProperties—内联样式,合并到与 className 相同的元素。
ui{ backdrop?: ClassValue; viewport?: ClassValue; popup?: ClassValue; glass?: ClassValue; overlay?: ClassValue; content?: ClassValue; title?: ClassValue; description?: ClassValue; body?: ClassValue; footer?: ClassValue }—按 data-slot 组织的内部槽位类名。
属性说明
data-open抽屉打开时存在。
data-closed抽屉关闭时存在。
data-starting-style抽屉开始进入动画时存在。
data-ending-style抽屉正在退出动画时存在。
data-expanded抽屉处于展开吸附点时存在。
data-nested抽屉嵌套在另一个抽屉内时存在。
data-nested-drawer-open抽屉内部还有另一个抽屉打开时存在。
data-nested-drawer-swiping嵌套抽屉正在滑动时存在。
data-swipe-dismiss抽屉通过滑动关闭时存在。
data-swipe-direction表示滑动方向(up、down、left 或 right)。
data-swiping抽屉正在滑动时存在。
data-slot标记内部部件(backdrop、viewport、popup、glass、overlay、content、title、description、body、footer),用于样式选择。

主题

组件使用共享玻璃材质。可以在父级调整 --ui-glass-* token,用 className 控制布局,并通过 ui 按 data-slot 调整内部槽位。组件级数值位于 src/theme/drawer.ts。Token 分层与预设见主题指南。

相关组件

  • Dialog — 居中的模态内容。
  • Alert Dialog — 明确的破坏性决定。
  • Popover — 非模态的上下文面板。