手势抽屉
概述
从屏幕边缘滑入的手势面板。与 SSheet(“带方向侧边的 dialog”)不同,抽屉拥有真实的领域状态机:吸附点、滑动进度、拖拽手柄与嵌套缩放都是 dialog 家族不具备的行为。
SDrawer 组合 Aria drawer 基础组件家族与 drawerVariants 样式配方(继承 sheetVariants,新增拖拽 handle 与可选的 swipeArea;6 种尺寸 × 4 个方向)。模态、焦点陷阱与关闭语义仍来自共享的 dialog 原语。
用法
特性
- 🧩 dialog 基座承载模态 — 继承 dialog 契约(
open/defaultOpen、焦点陷阱、焦点还原、Escape/外部关闭),并叠加抽屉状态机 - 🧭 4 个方向 —
side="top"/"bottom"/"left"/"right"(默认bottom);左右方向在 RTL 下镜像,上下方向限制高度并让内容区滚动 - 📏 吸附点 —
snapPoints接受分数(0.5)、像素偏移或 CSS 长度;用v-model:snap-point绑定当前等级;抽屉默认打开在第一个吸附点,关闭后重置回第一档 - 🪜 顺序吸附 —
snapToSequentialPoints逐级移动,而不是跳到最近点 - 🖐️ 滑动关闭 — 拖拽面板或手柄超过
closeThreshold即关闭;dismissible={false}强制显式操作;swipeDirection可覆盖关闭方向 - 👉 滑动打开 — 通过
swipeable启用边缘手势条(DrawerSwipeArea),具备轴锁定、方向阻尼、速度采样与滚动让位 - 🖼️ 页面缩进 —
DrawerIndent/DrawerIndentBackground让抽屉背后的页面随实时滑动进度缩放、位移与圆角(CSS 变量驱动) - 🧲 仅手柄拖拽 —
handleOnly限制仅手柄可拖;fixed固定面板同时内部内容滚动 - 🪗 嵌套抽屉 —
nested经DrawerRootNested渲染,拖拽、释放与打开状态与父级联动 - 🎛️ 模态三层级 —
modal支持true(完全模态)、'trap-focus'(陷阱焦点但保留外部指针事件)或false - 🔘 dialog 底部 —
showClose/showCancel/showConfirm,cancelText/confirmText本地化 - 📐 6 种尺寸 — xs–2xl
size;逐槽ui覆盖 - ⛶ 全屏 —
fullscreen/defaultFullscreen(或v-model:fullscreen)让面板从所锚定的那条边撑满视口;全屏期间吸附与拖拽均暂停生效 - ♿ 无障碍 —
role="dialog"、焦点移入面板、axe-core零违规
组件家族
SDrawer(样式层)— 入口包装组件;drawerVariants配方配合动态插槽转发DrawerRoot/DrawerRootNested(Aria)— 状态持有者;open、snapPoints、snapPoint、dismissible、nested、拖拽/滑动状态DrawerTrigger(Aria)— 打开者,接入aria-haspopup/aria-expandedDrawerPortal(Aria)— 传送边界DrawerOverlay(Aria)— 变暗的背景遮罩;透明度随实时滑动进度衰减DrawerPopup(Aria)— 焦点陷阱表面与拖拽手势宿主;位置完全由 CSS 变量驱动(--vean-drawer-snap-point-offset+--vean-drawer-swipe-movement-x/y)DrawerViewport(Aria)— 携带吸附点状态的可滚动区域DrawerSwipeArea(Aria)— 可选边缘手势条,滑动打开抽屉DrawerHandle(Aria)— 抓手柄;双击循环吸附点。DrawerCompact仅在side="bottom"时渲染DrawerIndent/DrawerIndentBackground(Aria)— 包裹抽屉背后的页面获得缩进效果;data-active标记打开状态,--vean-drawer-swipe-progress承载实时进度DrawerHeader/DrawerContent/DrawerFooter/DrawerTitle/DrawerDescription/DrawerClose/DrawerCancel/DrawerConfirm(Aria)— 包装 Dialog 的 chrome 基元;DOM 使用data-vean-drawer-*DrawerCompact(Aria)— 聚合组件;组合手柄、手势条、头部、内容与底部并暴露各插槽
演示
基础
嵌套
吸附点
滑动
表单输入
API
Aria 层
21Drawer
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
description | string | — | 对话框的描述。此描述用于辅助功能,若未提供 `description` 槽,则会在对话框内容中显示。 |
open | boolean | undefined | 对话框的受控打开状态。可通过 `v-model:open` 进行绑定。 |
defaultOpen | boolean | false | 对话框在初始渲染时的打开状态。当无需控制其打开状态时使用。 |
dir | Direction | — | 对话框的文本方向 |
draggable | boolean | false | 是否可以通过拖动对话框的标题来移动该对话框。 |
title | string | — | 对话框的标题。此标题用于辅助功能,若未提供 `title` 槽,则会显示在对话框的标题栏中。 |
icon | IconValue | — | 对话框的图标。该图标用于辅助功能,若未提供 `icon` 槽,则会显示在对话框的标题栏中。 |
pure | boolean | false | 是否使用不包含页眉和页脚的“纯版”对话框。
当您希望完全控制对话框内容且不需要内置页眉和页脚时,此选项非常有用。 |
portalProps | DrawerPortalProps | — | 转发给 portal 元素的属性。 |
popupProps | DrawerPopupProps | — | 转发给弹出窗口元素的属性。 |
triggerProps | DialogTriggerProps | — | 转发给触发元素的属性。 |
headerProps | DialogHeaderProps | — | 转发至 header 元素的属性。 |
contentProps | DialogContentProps | — | 转发给内容元素的属性。 |
footerProps | DialogFooterProps | — | 转发至页脚元素的属性。 |
closeProps | DialogCloseProps | — | 转发至 close 元素的属性。 |
fullscreen | boolean | undefined | 对话框的可控全屏状态。可通过 `v-model:fullscreen` 进行绑定。 |
showClose | boolean | true | 是否在对话框的标题栏中显示关闭按钮。 |
showFullscreen | boolean | true | 是否在对话框的标题栏中显示全屏切换按钮。 |
showCancel | boolean | 'onlyWarning' | 'onlyWarning' | 是否显示“取消”按钮。
当设置为 `onlyWarning` 时,只有当对话框是 `alertType="warning"` 的警告对话框时,才会显示“取消”按钮。
当设置为 `true` 时,将始终显示“取消”按钮。 |
cancelText | string | — | “取消”按钮的文本。此文本用于辅助功能,若未提供 `cancel` 插槽,则会在对话框的页脚中显示。
默认采用来自 `ConfigProvider` 的本地化 `dialog.cancel` 消息。 |
showConfirm | boolean | — | 当对话框为提示对话框时,是否显示确认按钮。
当对话框为提示对话框时,默认值为 `true`。 |
confirmText | string | — | “确认”按钮的文本。此文本用于辅助功能,若未提供 `confirm` 插槽,则会显示在对话框的页脚中。
默认采用来自 `ConfigProvider` 的本地化 `dialog.confirm` 消息。 |
overlayProps | DrawerOverlayProps | — | 转发给覆盖元素的属性。 |
titleProps | DialogTitleProps | — | 传递给 title 元素的属性。 |
descriptionProps | DialogDescriptionProps | — | 已将属性转发至 description 元素。 |
fullscreenProps | DialogFullscreenProps | — | 转发给全屏元素的属性。 |
cancelProps | DialogCancelProps | — | 转发给 cancel 元素的属性。 |
confirmProps | DialogConfirmProps | — | 转发给 confirm 元素的属性。 |
isAlert | boolean | false | 该对话框是否为警报对话框。警报对话框是一种会中断用户工作流程以传达重要信息并需要用户做出响应的对话框。
当设置为 `true` 时,对话框将具有 `role="alertdialog"` 属性,并需要提供 `DialogTitle`。此设置用于辅助功能支持。 |
alertType | DialogAlertType | — | 对话框的“alert”类型,当对话框为警报对话框时,该类型将决定默认图标和样式。 |
defaultFullscreen | boolean | false | 对话框初次渲染时的全屏状态。当您无需控制其全屏状态时使用此选项。 |
modal | import("../../types").ModalityTier | true | 模态级别。`true` 会阻断外部指针事件,`'trap-focus'` 仅捕获焦点,
`false` 保持界面非模态状态。 |
snapPoint | DrawerSnapPoint | null | — | 受控的快照点。可通过 `v-model:snapPoint` 进行绑定。 |
defaultSnapPoint | DrawerSnapPoint | null | — | 抽屉框初次渲染时使用的对齐点。当无需手动控制时使用。
默认值为 `snapPoints` 数组中的第一个条目。 |
snapToSequentialPoints | boolean | false | 当值为 `true` 时,跳转至下一个顺序上的定位点(每次一步)。
当值为 `false` 时,跳转至距离最近的定位点。 |
closeThreshold | number | 0.25 | 关闭阈值应作为抽屉大小的分数(0–1)。 |
swipeDirection | SwipeDirection | — | 用于关闭抽屉的滑动方向。默认方向为
与抽屉进入边缘(`side`)相反的方向。 |
fixed | boolean | — | 是否已修复。 |
dismissible | boolean | true | 是否可关闭。 |
nested | boolean | false | 无论是否嵌套。 |
side | Side | 'bottom' | 翻译方向。 |
noBodyStyles | boolean | — | 当 `true` 时,`body` 不会从抽屉中继承任何样式 |
handleOnly | boolean | false | 仅处理“whether”一词。 |
preventScrollRestoration | boolean | — | 是否阻止滚动恢复。 |
snapPoints | DrawerSnapPoint[] | — | 用于定位抽屉的对齐点。
使用 0 到 1 之间的数字表示视口高度的分数,
大于 1 的数字表示像素值,或使用 `px`/`rem` 单位的字符串。 |
handleProps | DrawerHandleProps | — | 转发至 handle 元素的属性。 |
swipeable | boolean | false | 在抽屉边缘渲染可选的“滑动打开”区域。 |
swipeAreaProps | DrawerSwipeAreaProps | — | 转发给滑动区域元素的属性。 |
class | ClassValue | — | drawer 的 popup 类 |
size | ThemeSize | — | 组件的视觉尺寸。 |
ui | Partial<DrawerUi> | — | 该组件的按槽类重写。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
cancel | MouseEvent | 当请求取消对话框时调用的事件处理程序。 |
click | PointerEvent | 当对话框触发器被激活时调用的事件处理程序。 |
fullscreen | MouseEvent | 当请求切换对话框的全屏状态时,会调用此事件处理程序。 |
confirm | MouseEvent | 当通过确认操作请求关闭对话框时,将调用此事件处理程序。 |
update:open | boolean | 当对话框的打开状态发生变化时调用的事件处理程序。 |
update:fullscreen | boolean | 当对话框的全屏状态发生变化时调用的事件处理程序。 |
escapeKeyDown | KeyboardEvent | 当 Esc 键被按下时触发的事件处理程序。可被阻止。 |
pointerDownOutside | PointerDownOutsideEvent | 当 `pointerdown` 事件发生在 `DismissableLayer` 外部时调用的事件处理程序。可被阻止。 |
focusOutside | FocusOutsideEvent | 当焦点移出 `DismissableLayer` 时触发的事件处理程序。可被阻止。 |
interactOutside | PointerDownOutsideEvent | FocusOutsideEvent | 当在 `DismissableLayer` 外部发生交互时触发的事件处理程序。具体而言,当 `pointerdown`
事件在该区域外部发生,或焦点移出该区域时触发。此事件可被阻止。 |
openAutoFocus | Event | 在打开页面时自动聚焦时触发的事件处理程序。可被阻止。 |
closeAutoFocus | Event | 在关闭时自动聚焦时触发的事件处理程序。可被阻止。 |
drag | number | 在拖动时显示的实时进度:0 表示完全展开,1 表示完全收起。 |
release | boolean | 在拖动手势释放时触发;若抽屉保持打开状态,则返回 `true`。 |
close | — | 在关闭时触发。 |
update:snapPoint | DrawerSnapPoint | null | 当快照点值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
default | props: DialogCompactBaseSlotProps | 默认插槽的自定义内容。 |
trigger | DialogCompactBaseSlotProps | 触发槽的自定义内容。 |
title | DialogCompactBaseSlotProps | 标题槽位的自定义内容。 |
description | DialogCompactBaseSlotProps | 描述字段的自定义内容。 |
close | DialogCompactBaseSlotProps | close 插槽的自定义内容。 |
fullscreen | DialogCompactBaseSlotProps | 全屏插槽的自定义内容。 |
footer | DialogCompactBaseSlotProps | 页脚位置的自定义内容。 |
cancel | DialogCompactBaseSlotProps | “cancel”插槽的自定义内容。 |
confirm | DialogCompactBaseSlotProps | 用于 confirm 插槽的自定义内容。 |
DrawerCancel
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否已禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
cancel | MouseEvent | 当请求取消对话框时调用的事件处理程序。 |
DrawerClose
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否已禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
close | MouseEvent | 当请求关闭对话框时调用的事件处理程序。 |
DrawerCompact
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
description | string | — | 对话框的描述。此描述用于辅助功能,若未提供 `description` 槽,则会在对话框内容中显示。 |
open | boolean | undefined | 对话框的受控打开状态。可通过 `v-model:open` 进行绑定。 |
defaultOpen | boolean | false | 对话框在初始渲染时的打开状态。当无需控制其打开状态时使用。 |
dir | Direction | — | 对话框的文本方向 |
draggable | boolean | false | 是否可以通过拖动对话框的标题来移动该对话框。 |
title | string | — | 对话框的标题。此标题用于辅助功能,若未提供 `title` 槽,则会显示在对话框的标题栏中。 |
icon | IconValue | — | 对话框的图标。该图标用于辅助功能,若未提供 `icon` 槽,则会显示在对话框的标题栏中。 |
pure | boolean | false | 是否使用不包含页眉和页脚的“纯版”对话框。
当您希望完全控制对话框内容且不需要内置页眉和页脚时,此选项非常有用。 |
portalProps | DrawerPortalProps | — | 转发给 portal 元素的属性。 |
popupProps | DrawerPopupProps | — | 转发给弹出窗口元素的属性。 |
triggerProps | DialogTriggerProps | — | 转发给触发元素的属性。 |
headerProps | DialogHeaderProps | — | 转发至 header 元素的属性。 |
contentProps | DialogContentProps | — | 转发给内容元素的属性。 |
footerProps | DialogFooterProps | — | 转发至页脚元素的属性。 |
closeProps | DialogCloseProps | — | 转发至 close 元素的属性。 |
fullscreen | boolean | undefined | 对话框的可控全屏状态。可通过 `v-model:fullscreen` 进行绑定。 |
showClose | boolean | true | 是否在对话框的标题栏中显示关闭按钮。 |
showFullscreen | boolean | true | 是否在对话框的标题栏中显示全屏切换按钮。 |
showCancel | boolean | 'onlyWarning' | 'onlyWarning' | 是否显示“取消”按钮。
当设置为 `onlyWarning` 时,只有当对话框是 `alertType="warning"` 的警告对话框时,才会显示“取消”按钮。
当设置为 `true` 时,将始终显示“取消”按钮。 |
cancelText | string | — | “取消”按钮的文本。此文本用于辅助功能,若未提供 `cancel` 插槽,则会在对话框的页脚中显示。
默认采用来自 `ConfigProvider` 的本地化 `dialog.cancel` 消息。 |
showConfirm | boolean | — | 当对话框为提示对话框时,是否显示确认按钮。
当对话框为提示对话框时,默认值为 `true`。 |
confirmText | string | — | “确认”按钮的文本。此文本用于辅助功能,若未提供 `confirm` 插槽,则会显示在对话框的页脚中。
默认采用来自 `ConfigProvider` 的本地化 `dialog.confirm` 消息。 |
overlayProps | DrawerOverlayProps | — | 转发给覆盖元素的属性。 |
titleProps | DialogTitleProps | — | 传递给 title 元素的属性。 |
descriptionProps | DialogDescriptionProps | — | 已将属性转发至 description 元素。 |
fullscreenProps | DialogFullscreenProps | — | 转发给全屏元素的属性。 |
cancelProps | DialogCancelProps | — | 转发给 cancel 元素的属性。 |
confirmProps | DialogConfirmProps | — | 转发给 confirm 元素的属性。 |
isAlert | boolean | false | 该对话框是否为警报对话框。警报对话框是一种会中断用户工作流程以传达重要信息并需要用户做出响应的对话框。
当设置为 `true` 时,对话框将具有 `role="alertdialog"` 属性,并需要提供 `DialogTitle`。此设置用于辅助功能支持。 |
alertType | DialogAlertType | — | 对话框的“alert”类型,当对话框为警报对话框时,该类型将决定默认图标和样式。 |
defaultFullscreen | boolean | false | 对话框初次渲染时的全屏状态。当您无需控制其全屏状态时使用此选项。 |
modal | import("../../types").ModalityTier | true | 模态级别。`true` 会阻断外部指针事件,`'trap-focus'` 仅捕获焦点,
`false` 保持界面非模态状态。 |
snapPoint | DrawerSnapPoint | null | — | 受控的快照点。可通过 `v-model:snapPoint` 进行绑定。 |
defaultSnapPoint | DrawerSnapPoint | null | — | 抽屉框初次渲染时使用的对齐点。当无需手动控制时使用。
默认值为 `snapPoints` 数组中的第一个条目。 |
snapToSequentialPoints | boolean | false | 当值为 `true` 时,跳转至下一个顺序上的定位点(每次一步)。
当值为 `false` 时,跳转至距离最近的定位点。 |
closeThreshold | number | 0.25 | 关闭阈值应作为抽屉大小的分数(0–1)。 |
swipeDirection | SwipeDirection | — | 用于关闭抽屉的滑动方向。默认方向为
与抽屉进入边缘(`side`)相反的方向。 |
fixed | boolean | — | 是否已修复。 |
dismissible | boolean | true | 是否可关闭。 |
nested | boolean | false | 无论是否嵌套。 |
side | Side | 'bottom' | 翻译方向。 |
noBodyStyles | boolean | — | 当 `true` 时,`body` 不会从抽屉中继承任何样式 |
handleOnly | boolean | false | 仅处理“whether”一词。 |
preventScrollRestoration | boolean | — | 是否阻止滚动恢复。 |
snapPoints | DrawerSnapPoint[] | — | 用于定位抽屉的对齐点。
使用 0 到 1 之间的数字表示视口高度的分数,
大于 1 的数字表示像素值,或使用 `px`/`rem` 单位的字符串。 |
handleProps | DrawerHandleProps | — | 转发至 handle 元素的属性。 |
swipeable | boolean | false | 在抽屉边缘渲染可选的“滑动打开”区域。 |
swipeAreaProps | DrawerSwipeAreaProps | — | 转发给滑动区域元素的属性。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
cancel | MouseEvent | 当请求取消对话框时调用的事件处理程序。 |
click | PointerEvent | 当对话框触发器被激活时调用的事件处理程序。 |
fullscreen | MouseEvent | 当请求切换对话框的全屏状态时,会调用此事件处理程序。 |
confirm | MouseEvent | 当通过确认操作请求关闭对话框时,将调用此事件处理程序。 |
update:open | boolean | 当对话框的打开状态发生变化时调用的事件处理程序。 |
update:fullscreen | boolean | 当对话框的全屏状态发生变化时调用的事件处理程序。 |
escapeKeyDown | KeyboardEvent | 当 Esc 键被按下时触发的事件处理程序。可被阻止。 |
pointerDownOutside | PointerDownOutsideEvent | 当 `pointerdown` 事件发生在 `DismissableLayer` 外部时调用的事件处理程序。可被阻止。 |
focusOutside | FocusOutsideEvent | 当焦点移出 `DismissableLayer` 时触发的事件处理程序。可被阻止。 |
interactOutside | PointerDownOutsideEvent | FocusOutsideEvent | 当在 `DismissableLayer` 外部发生交互时触发的事件处理程序。具体而言,当 `pointerdown`
事件在该区域外部发生,或焦点移出该区域时触发。此事件可被阻止。 |
openAutoFocus | Event | 在打开页面时自动聚焦时触发的事件处理程序。可被阻止。 |
closeAutoFocus | Event | 在关闭时自动聚焦时触发的事件处理程序。可被阻止。 |
drag | number | 在拖动时显示的实时进度:0 表示完全展开,1 表示完全收起。 |
release | boolean | 在拖动手势释放时触发;若抽屉保持打开状态,则返回 `true`。 |
close | — | 在关闭时触发。 |
update:snapPoint | DrawerSnapPoint | null | 当快照点值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
default | props: DialogCompactBaseSlotProps | 默认插槽的自定义内容。 |
trigger | DialogCompactBaseSlotProps | 触发槽的自定义内容。 |
title | DialogCompactBaseSlotProps | 标题槽位的自定义内容。 |
description | DialogCompactBaseSlotProps | 描述字段的自定义内容。 |
close | DialogCompactBaseSlotProps | close 插槽的自定义内容。 |
fullscreen | DialogCompactBaseSlotProps | 全屏插槽的自定义内容。 |
footer | DialogCompactBaseSlotProps | 页脚位置的自定义内容。 |
cancel | DialogCompactBaseSlotProps | “cancel”插槽的自定义内容。 |
confirm | DialogCompactBaseSlotProps | 用于 confirm 插槽的自定义内容。 |
DrawerConfirm
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否已禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
confirm | MouseEvent | 当通过确认操作请求关闭对话框时,将调用此事件处理程序。 |
DrawerContent
DrawerDescription
DrawerFooter
DrawerHandle
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
preventCycle | boolean | — | 是否防止循环。 |
DrawerHeader
DrawerIndent
DrawerIndentBackground
DrawerOverlay
DrawerPopup
DrawerPortal
DrawerRoot
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
open | boolean | undefined | 对话框的受控打开状态。可通过 `v-model:open` 进行绑定。 |
defaultOpen | boolean | false | 对话框在初始渲染时的打开状态。当无需控制其打开状态时使用。 |
dir | Direction | — | 对话框的文本方向 |
draggable | boolean | false | 是否可以通过拖动对话框的标题来移动该对话框。 |
fullscreen | boolean | undefined | 对话框的可控全屏状态。可通过 `v-model:fullscreen` 进行绑定。 |
isAlert | boolean | false | 该对话框是否为警报对话框。警报对话框是一种会中断用户工作流程以传达重要信息并需要用户做出响应的对话框。
当设置为 `true` 时,对话框将具有 `role="alertdialog"` 属性,并需要提供 `DialogTitle`。此设置用于辅助功能支持。 |
alertType | DialogAlertType | — | 对话框的“alert”类型,当对话框为警报对话框时,该类型将决定默认图标和样式。 |
defaultFullscreen | boolean | false | 对话框初次渲染时的全屏状态。当您无需控制其全屏状态时使用此选项。 |
modal | import("../../types").ModalityTier | true | 模态级别。`true` 会阻断外部指针事件,`'trap-focus'` 仅捕获焦点,
`false` 保持界面非模态状态。 |
snapPoint | DrawerSnapPoint | null | — | 受控的快照点。可通过 `v-model:snapPoint` 进行绑定。 |
defaultSnapPoint | DrawerSnapPoint | null | — | 抽屉框初次渲染时使用的对齐点。当无需手动控制时使用。
默认值为 `snapPoints` 数组中的第一个条目。 |
snapToSequentialPoints | boolean | false | 当值为 `true` 时,跳转至下一个顺序上的定位点(每次一步)。
当值为 `false` 时,跳转至距离最近的定位点。 |
closeThreshold | number | 0.25 | 关闭阈值应作为抽屉大小的分数(0–1)。 |
swipeDirection | SwipeDirection | — | 用于关闭抽屉的滑动方向。默认方向为
与抽屉进入边缘(`side`)相反的方向。 |
fixed | boolean | — | 是否已修复。 |
dismissible | boolean | true | 是否可关闭。 |
nested | boolean | false | 无论是否嵌套。 |
side | Side | 'bottom' | 翻译方向。 |
noBodyStyles | boolean | — | 当 `true` 时,`body` 不会从抽屉中继承任何样式 |
handleOnly | boolean | false | 仅处理“whether”一词。 |
preventScrollRestoration | boolean | — | 是否阻止滚动恢复。 |
snapPoints | DrawerSnapPoint[] | — | 用于定位抽屉的对齐点。
使用 0 到 1 之间的数字表示视口高度的分数,
大于 1 的数字表示像素值,或使用 `px`/`rem` 单位的字符串。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:open | boolean | 当对话框的打开状态发生变化时调用的事件处理程序。 |
update:fullscreen | boolean | 当对话框的全屏状态发生变化时调用的事件处理程序。 |
drag | number | 在拖动时显示的实时进度:0 表示完全展开,1 表示完全收起。 |
release | boolean | 在拖动手势释放时触发;若抽屉保持打开状态,则返回 `true`。 |
close | — | 在关闭时触发。 |
update:snapPoint | DrawerSnapPoint | null | 当快照点值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
default | { open: boolean; close: () => void; } | 默认插槽的自定义内容。 |
DrawerRootNested
DrawerSwipeArea
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
swipeDirection | SwipeDirection | — | 覆盖打开抽屉的滑动方向。默认值为与根滑动方向相反的方向。 |
disabled | boolean | false | 禁用“滑动打开”功能。 |
DrawerTitle
DrawerTrigger
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否已禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
click | PointerEvent | 当对话框触发器被激活时调用的事件处理程序。 |
DrawerViewport
注意事项
架构与对标差异
DrawerCompact 负责手柄/手势条/遮罩/弹层/头部/内容/底部组合与拖拽/吸附状态流(经 useDrawerSnapPoints 与 useSwipeDismiss),所有基础组件保持零样式,仅由 UI 包装组件注入 drawerVariants 类。弹层 transform 完全由 CSS 变量驱动——手势层只写变量、从不写内联 transform——吸附归位、松手回弹与关闭退出都由 CSS transition 承接。这与 Base UI Drawer 的模型一致。Ant Design、Element Plus、Mantine、Naive UI 提供单一样式化抽屉;带 snapPoints 的专用可拖拽面板通常是独立库(vaul、Base UI Drawer)。VeanUI 内联暴露逐槽 *Props、size 尺寸体系与吸附/缩进/拖拽/滑动模型。
| 能力 | VeanUI | shadcn/ui + vaul | reka-ui Drawer | Base UI | Ant Design | Element Plus | Mantine |
|---|---|---|---|---|---|---|---|
| 复用 dialog 原语 | ✅ | ✅ | ✅ | ✅ | — | — | — |
| Aria/样式分离 | ✅ | ✅ | ✅ | ✅ | — | — | — |
| 拖拽关闭 | ✅ | ✅ | ✅ | ✅ | — | — | ✅ |
| 吸附点 | ✅ | ✅ | ✅ | ✅ | — | — | — |
| 滑动打开区域 | ✅ | — | ✅ | ✅ | — | — | — |
| 页面缩进效果 | ✅ | ✅ | — | ✅ | — | — | — |
| 嵌套抽屉 | ✅ | ✅ | ✅ | ✅ | — | — | — |
| 模态三层级 | ✅ | — | ✅ | ✅ | — | — | — |
| 尺寸(6) | ✅ | — | — | — | — | — | — |
— = 不支持或采用不同交互模型。
运行时注意
modal默认true;面板传送至document.body,body 滚动由 hide-others 层锁定。'trap-focus'层级保留外部指针事件,但仍然陷阱焦点。side决定锚定边缘。上下方向(top/bottom)将面板高度限制在calc(100dvh - 2rem),长内容在content槽内滚动而不会溢出视口;左右方向铺满视口高度并限制宽度。- 拖拽关闭使用指针捕获;
dismissible(默认true)允许超过closeThreshold松手关闭。设false以强制显式操作。swipeDirection可覆盖关闭方向(默认为入场边的反方向)。 - 横向 side 本版本仅支持纵向吸附——
snapPoints按纵向轴解析,left/right的吸附行为尚未支持。 snapPoints接受分数(0–1)、像素值(> 1)或 CSS 长度字符串;snapPoint追踪当前等级,用v-model:snap-point绑定。抽屉默认打开在第一个吸附点,关闭后重置回第一档。DrawerCompact仅在side="bottom"时渲染拖拽手柄;其他方向请手动组合DrawerHandle。handleOnly限制仅手柄可拖;fixed保持面板固定同时内部内容滚动。swipeable在抽屉边缘渲染手势条;抽屉打开时该区域不生效。nested经DrawerRootNested渲染;每个嵌套抽屉与父级协调拖拽与释放。- 全屏会定义面板的尺寸并冻结拖拽(与 dialog 在全屏时禁用 draggable 一致):低于「完全打开」的静止吸附档会把面板重新向下平移,使其越过锚定边的那一半落到屏幕外,而把面板拖离该边缘也与这个 prop 的语义相矛盾。关闭全屏后吸附与拖拽恢复;
snapPoints始终保留配置。 - 由于拖拽被暂停,全屏下的关闭只能走显式路径:关闭按钮、Escape,以及非模态抽屉的外部点击。因此「模态 + 全屏 +
showClose={false}+dismissible={false}」会让用户无法退出——需要可退出时请保留关闭按钮(或使用modal={false})。 - 全屏期间手柄不再循环档位,因此不会在背后改写
snapPoint。 - 抽屉自身不渲染全屏按钮,因此 dialog 的
showFullscreen在这里无效——请用v-model:fullscreen/defaultFullscreen驱动状态,或在面板内自行放置控件。 - 非受控的全屏状态不会跨关闭保留:重新打开时回到
defaultFullscreen(与 dialog 的重置行为一致)。
从 BottomSheet 迁移
v0.50.0 对整个家族做了更名——bottom-sheet 名称已退役。
| 旧名 | 新名 |
|---|---|
SBottomSheet | SDrawer |
BottomSheetRoot / BottomSheetRootNested | DrawerRoot / DrawerRootNested |
BottomSheetPopup / BottomSheetOverlay | DrawerPopup / DrawerOverlay |
BottomSheetHandle / BottomSheetCompact | DrawerHandle / DrawerCompact |
BottomSheetTitle / BottomSheetDescription | DrawerTitle / DrawerDescription |
BottomSheetHeader / BottomSheetContent / BottomSheetFooter | DrawerHeader / DrawerContent / DrawerFooter |
BottomSheetTrigger / BottomSheetClose / BottomSheetCancel / BottomSheetConfirm | DrawerTrigger / DrawerClose / DrawerCancel / DrawerConfirm |
v-model:active-snap-point | v-model:snap-point |
direction prop(Aria) | side prop |
@vean/aria/bottom-sheet | @vean/aria/drawer |
data-vean-bottom-sheet-*、soybean-bottom-sheet-dragging | data-vean-drawer-*、soybean-drawer-dragging |
data-vean-bottom-sheet-scale | 随 scale-background 引擎移除(见下) |
原 SDrawer(带侧边的 dialog)已更名为 SSheet。侧边面板 API 见 Sheet。
从 vaul 式引擎迁移
v0.50.0 以 Base UI 风格引擎替换了 vaul 式内核,公开面变化:
| 旧 | 新 |
|---|---|
shouldScaleBackground / setBackgroundColorOnScale | 已移除。在 DrawerRoot 内用 DrawerIndent + DrawerIndentBackground 包裹页面 |
fadeFromIndex | 已移除;遮罩透明度随滑动进度连续衰减 |
snapPoint 默认 null | 默认取 snapPoints 第一项(打开即定位在吸附点上) |
拖拽方向从 side 隐式推导 | 仍为默认行为,可用 swipeDirection 覆盖 |
| 命令式 transform | CSS 变量(--vean-drawer-snap-point-offset、--vean-drawer-swipe-movement-x/y) |
<!-- 旧 -->
<SBottomSheet v-model:open="open" v-model:active-snap-point="snap" :snap-points="[0.5, 1]">
<template #trigger><SButton>打开</SButton></template>
内容
</SBottomSheet>
<!-- 新 -->
<SDrawer v-model:open="open" v-model:snap-point="snap" :snap-points="[0.5, 1]">
<template #trigger><SButton>打开</SButton></template>
内容
</SDrawer>背景缩放的迁移示例:
<!-- 旧 -->
<SBottomSheet v-model:open="open" should-scale-background>
<div data-vean-drawer-scale>页面</div>
</SBottomSheet>
<!-- 新 -->
<SDrawer v-model:open="open">
<DrawerIndent class="page-indent">页面</DrawerIndent>
<template #trigger><SButton>打开</SButton></template>
</SDrawer>Roadmap
横向吸附点、触摸管线的真机验证(iOS Safari / Android Chrome),以及 iOS 虚拟键盘协调。
FAQ
如何把抽屉锚定到其他边缘?
设置 side 为 top/bottom/left/right:
<SDrawer v-model:open="open" side="left" title="筛选">
<template #trigger><SButton>打开</SButton></template>
<div>抽屉内容</div>
</SDrawer>如何启用吸附点?
传入分数、像素或 CSS 长度数组,并绑定当前等级:
<SDrawer v-model:open="open" v-model:snap-point="snapPoint" :snap-points="[0.4, 0.8, 1]" title="筛选">
<template #trigger><SButton>打开</SButton></template>
<div>抽屉内容</div>
</SDrawer>如何用滑动手势打开抽屉?
设置 swipeable。会在面板 side 所在边缘渲染手势条,滑动方向与之相反:
<SDrawer v-model:open="open" swipeable title="详情">
<template #trigger><SButton>打开</SButton></template>
<div>抽屉内容</div>
</SDrawer>如何禁用拖拽关闭?
设置 dismissible={false} 以要求显式操作:
<SDrawer :dismissible="false" title="确认">
<template #trigger><SButton>打开</SButton></template>
<div>抽屉内容</div>
</SDrawer>如何限制仅手柄可拖?
设置 handle-only:
<SDrawer handle-only title="详情">
<template #trigger><SButton>打开</SButton></template>
<div>抽屉内容</div>
</SDrawer>如何构建仍陷阱焦点的非模态侧面板?
使用 'trap-focus' 层级:
<SDrawer v-model:open="open" modal="trap-focus" title="检查器">
<template #trigger><SButton>打开</SButton></template>
<div>抽屉内容</div>
</SDrawer>如何让抽屉全屏?
绑定 v-model:fullscreen,或用 default-fullscreen 让它初始即全屏。面板会从 side 那侧撑满视口且不再响应拖拽,因此吸附与拖拽都要等关闭全屏后才恢复:
<SDrawer v-model:open="open" v-model:fullscreen="fullscreen" :snap-points="[0.6, 1]" title="详情">
<template #trigger><SButton>打开</SButton></template>
<div>抽屉内容</div>
</SDrawer>