Components
Back to catalog
Component detail entry
Overlay
@vean/ui
SDrawer

Drawer

Drawer belongs to the Overlay category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Drawer

Overview

A gesture-driven panel that slides in from an edge of the screen. Unlike SSheet (a dialog with a side), the drawer owns a real domain state machine: snap points, swipe progress, a drag handle, and nested scaling are behaviour the dialog family does not have.

SDrawer combines the Aria drawer primitive family with the drawerVariants style recipe (extends sheetVariants, adds a drag handle and an opt-in swipeArea; 6 sizes × 4 sides). Modality, focus trapping and dismissal still come from the shared dialog primitives.

Usage

Features

  • 🧩 Dialog-backed modality — inherits the dialog contract (open/defaultOpen, focus trap, focus restoration, Escape/outside dismissal) while adding the drawer state machine
  • 🧭 4 sides — side="top"/"bottom"/"left"/"right" (default bottom); horizontal sides are mirrored under RTL, vertical sides cap their height and scroll their content
  • 📏 Snap points — snapPoints accepts fractions (0.5), pixel offsets or CSS lengths; bind the active level with v-model:snap-point; the drawer opens at the first snap point and resets to it when closed
  • 🪜 Sequential snapping — snapToSequentialPoints walks one level at a time instead of jumping to the nearest point
  • 🖐️ Swipe dismiss — dragging the panel or the handle past closeThreshold closes it; dismissible={false} forces an explicit action; swipeDirection overrides the dismiss direction
  • 👉 Swipe to open — opt into an edge gesture strip with swipeable (DrawerSwipeArea), with axis locking, direction damping, sampled velocity and scroll yielding
  • 🖼️ Page indent — DrawerIndent / DrawerIndentBackground scale, shift and round the page behind the drawer following the live swipe progress (CSS-variable driven)
  • 🧲 Handle-only dragging — handleOnly restricts the gesture to the handle; fixed pins the panel while its content scrolls
  • 🪗 Nested drawers — nested renders through DrawerRootNested so drag, release and open state stay coordinated with the parent
  • 🎛️ Modality tiers — modal accepts true (full modal), 'trap-focus' (focus trapped, outside pointer events alive) or false
  • 🔘 Dialog footer — showClose/showCancel/showConfirm with localized cancelText/confirmText
  • 📐 6 sizes — xs–2xl size; per-slot ui overrides
  • ⛶ Fullscreen — fullscreen/defaultFullscreen (or v-model:fullscreen) grow the panel to the viewport from its anchored edge; snapping and dragging are suspended while fullscreen
  • ♿ Accessible — role="dialog", focus moves into the panel, axe-core clean

Component family

  • SDrawer (styled) — the entry wrapper; drawerVariants recipe with dynamic slot forwarding
  • DrawerRoot / DrawerRootNested (Aria) — the state owner; open, snapPoints, snapPoint, dismissible, nested, drag/swipe state
  • DrawerTrigger (Aria) — the opener, wired to aria-haspopup/aria-expanded
  • DrawerPortal (Aria) — the teleport boundary
  • DrawerOverlay (Aria) — the dimmed backdrop; fades with the live swipe progress
  • DrawerPopup (Aria) — the focus-trapped surface and the drag gesture host; its position is driven entirely by CSS variables (--vean-drawer-snap-point-offset + --vean-drawer-swipe-movement-x/y)
  • DrawerViewport (Aria) — the scrollable region that carries snap-point state
  • DrawerSwipeArea (Aria) — the opt-in edge strip that opens the drawer by swipe
  • DrawerHandle (Aria) — the grab handle; double-tap cycles snap points. DrawerCompact renders it only for side="bottom"
  • DrawerIndent / DrawerIndentBackground (Aria) — wrap the page behind the drawer to get the indent effect; data-active marks an open drawer and --vean-drawer-swipe-progress carries the live progress
  • DrawerHeader / DrawerContent / DrawerFooter / DrawerTitle / DrawerDescription / DrawerClose / DrawerCancel / DrawerConfirm (Aria) — chrome primitives wrapping Dialog; DOM uses data-vean-drawer-*
  • DrawerCompact (Aria) — the aggregated composite; composes handle, swipe area, header, content and footer and exposes the slots

Demos

Basic

Nested

Snap Points

Swipe

Form Inputs

API

Aria Layer

21

Drawer

51 Props16 Emits9 Slots
Props
PropTypeDefaultDescription
description
string
—
The description of the dialog. This is used for accessibility purposes and will be rendered in the content of the dialog if the `description` slot is not provided.
open
boolean
undefined
The controlled open state of the dialog. Can be bound with `v-model:open`.
defaultOpen
boolean
false
The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
dir
Direction
—
The text direction of the dialog
draggable
boolean
false
Whether the dialog can be moved by dragging its header.
title
string
—
The title of the dialog. This is used for accessibility purposes and will be rendered in the header of the dialog if the `title` slot is not provided.
icon
IconValue
—
The icon of the dialog. This is used for accessibility purposes and will be rendered in the header of the dialog if the `icon` slot is not provided.
pure
boolean
false
Whether to use the pure version of the dialog, which does not include the header and footer. This is useful when you want to fully control the content of the dialog and do not need the built-in header and footer.
portalProps
DrawerPortalProps
—
Properties forwarded to the portal element.
popupProps
DrawerPopupProps
—
Properties forwarded to the popup element.
triggerProps
DialogTriggerProps
—
Properties forwarded to the trigger element.
headerProps
DialogHeaderProps
—
Properties forwarded to the header element.
contentProps
DialogContentProps
—
Properties forwarded to the content element.
footerProps
DialogFooterProps
—
Properties forwarded to the footer element.
closeProps
DialogCloseProps
—
Properties forwarded to the close element.
fullscreen
boolean
undefined
The controlled fullscreen state of the dialog. Can be bound with `v-model:fullscreen`.
showClose
boolean
true
Whether show the close button in the header of the dialog.
showFullscreen
boolean
true
Whether show the fullscreen toggle button in the header of the dialog.
showCancel
boolean | 'onlyWarning'
'onlyWarning'
Whether to show the cancel button. When set to `onlyWarning`, the cancel button will only be shown when the dialog is an alert dialog with `alertType="warning"`. When set to `true`, the cancel button will always be shown.
cancelText
string
—
The text of the cancel button. This is used for accessibility purposes and will be rendered in the footer of the dialog if the `cancel` slot is not provided. Defaults to the localized `dialog.cancel` message from `ConfigProvider`.
showConfirm
boolean
—
Whether to show the confirm button when the dialog is an alert dialog. The default value is `true` when the dialog is an alert dialog.
confirmText
string
—
The text of the confirm button. This is used for accessibility purposes and will be rendered in the footer of the dialog if the `confirm` slot is not provided. Defaults to the localized `dialog.confirm` message from `ConfigProvider`.
overlayProps
DrawerOverlayProps
—
Properties forwarded to the overlay element.
titleProps
DialogTitleProps
—
Properties forwarded to the title element.
descriptionProps
DialogDescriptionProps
—
Properties forwarded to the description element.
fullscreenProps
DialogFullscreenProps
—
Properties forwarded to the fullscreen element.
cancelProps
DialogCancelProps
—
Properties forwarded to the cancel element.
confirmProps
DialogConfirmProps
—
Properties forwarded to the confirm element.
isAlert
boolean
false
Whether the dialog is an alert dialog. An alert dialog is a dialog that interrupts the user's workflow to communicate an important message and requires a response. When set to `true`, the dialog will have `role="alertdialog"` and will require a `DialogTitle` to be provided. This is used for accessibility purposes.
alertType
DialogAlertType
—
The alert type of the dialog, which determines the default icon and styles when the dialog is an alert dialog.
defaultFullscreen
boolean
false
The fullscreen state of the dialog when it is initially rendered. Use when you do not need to control its fullscreen state.
modal
import("../../types").ModalityTier
true
Modality tier. `true` blocks outside pointer events, `'trap-focus'` only traps focus, `false` keeps the surface non-modal.
snapPoint
DrawerSnapPoint | null
—
The controlled snap point. Can be bound with `v-model:snapPoint`.
defaultSnapPoint
DrawerSnapPoint | null
—
The snap point used when the drawer is initially rendered. Use when you do not need to control it. Defaults to the first entry of `snapPoints`.
snapToSequentialPoints
boolean
false
When `true`, snaps to the next sequential snap point (one step at a time). When `false`, snaps to the nearest snap point by distance.
closeThreshold
number
0.25
Close threshold as a fraction of the drawer size (0–1).
swipeDirection
SwipeDirection
—
The swipe direction that dismisses the drawer. Defaults to the direction opposite the drawer's entry edge (`side`).
fixed
boolean
—
Whether fixed.
dismissible
boolean
true
Whether dismissible.
nested
boolean
false
Whether nested.
side
Side
'bottom'
Direction.
noBodyStyles
boolean
—
When `true` the `body` doesn't get any styles assigned from the drawer
handleOnly
boolean
false
Whether handle only.
preventScrollRestoration
boolean
—
Whether prevent scroll restoration.
snapPoints
DrawerSnapPoint[]
—
Snap points used to position the drawer. Use numbers between 0 and 1 to represent fractions of the viewport height, numbers greater than 1 as pixel values, or strings in `px`/`rem` units.
handleProps
DrawerHandleProps
—
Properties forwarded to the handle element.
swipeable
boolean
false
Render the opt-in swipe-to-open area at the drawer's edge.
swipeAreaProps
DrawerSwipeAreaProps
—
Properties forwarded to the swipe area element.
class
ClassValue
—
the popup class of the drawer
size
ThemeSize
—
Visual size of the component.
ui
Partial<DrawerUi>
—
Per-slot class overrides for the component.
Emits
Emit NameParametersDescription
cancel
MouseEvent
Event handler called when the dialog is requested to be canceled.
click
PointerEvent
Event handler called when the dialog trigger is activated.
fullscreen
MouseEvent
Event handler called when the fullscreen state of the dialog is requested to be toggled.
confirm
MouseEvent
Event handler called when the dialog is requested to be closed by confirming.
update:open
boolean
Event handler called when the open state of the dialog changes.
update:fullscreen
boolean
Event handler called when the fullscreen state of the dialog changes.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
interactOutside
PointerDownOutsideEvent | FocusOutsideEvent
Event handler called when an interaction happens outside the `DismissableLayer`. Specifically, when a `pointerdown` event happens outside or focus moves outside of it. Can be prevented.
openAutoFocus
Event
Event handler called when auto-focusing on open. Can be prevented.
closeAutoFocus
Event
Event handler called when auto-focusing on close. Can be prevented.
drag
number
Emitted while dragging with the live progress: 0 fully open, 1 closed.
release
boolean
Emitted when a drag gesture releases; `true` when the drawer stays open.
close
—
Emitted when close occurs.
update:snapPoint
DrawerSnapPoint | null
Emitted when the snap point value changes.
Slots
Slot NameParametersDescription
default
props: DialogCompactBaseSlotProps
Custom content for the default slot.
trigger
DialogCompactBaseSlotProps
Custom content for the trigger slot.
title
DialogCompactBaseSlotProps
Custom content for the title slot.
description
DialogCompactBaseSlotProps
Custom content for the description slot.
close
DialogCompactBaseSlotProps
Custom content for the close slot.
fullscreen
DialogCompactBaseSlotProps
Custom content for the fullscreen slot.
footer
DialogCompactBaseSlotProps
Custom content for the footer slot.
cancel
DialogCompactBaseSlotProps
Custom content for the cancel slot.
confirm
DialogCompactBaseSlotProps
Custom content for the confirm slot.

DrawerCancel

4 Props1 Emits
Props
PropTypeDefaultDescription
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
cancel
MouseEvent
Event handler called when the dialog is requested to be canceled.

DrawerClose

4 Props1 Emits
Props
PropTypeDefaultDescription
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
close
MouseEvent
Event handler called when the dialog is requested to be closed.

DrawerCompact

48 Props16 Emits9 Slots
Props
PropTypeDefaultDescription
description
string
—
The description of the dialog. This is used for accessibility purposes and will be rendered in the content of the dialog if the `description` slot is not provided.
open
boolean
undefined
The controlled open state of the dialog. Can be bound with `v-model:open`.
defaultOpen
boolean
false
The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
dir
Direction
—
The text direction of the dialog
draggable
boolean
false
Whether the dialog can be moved by dragging its header.
title
string
—
The title of the dialog. This is used for accessibility purposes and will be rendered in the header of the dialog if the `title` slot is not provided.
icon
IconValue
—
The icon of the dialog. This is used for accessibility purposes and will be rendered in the header of the dialog if the `icon` slot is not provided.
pure
boolean
false
Whether to use the pure version of the dialog, which does not include the header and footer. This is useful when you want to fully control the content of the dialog and do not need the built-in header and footer.
portalProps
DrawerPortalProps
—
Properties forwarded to the portal element.
popupProps
DrawerPopupProps
—
Properties forwarded to the popup element.
triggerProps
DialogTriggerProps
—
Properties forwarded to the trigger element.
headerProps
DialogHeaderProps
—
Properties forwarded to the header element.
contentProps
DialogContentProps
—
Properties forwarded to the content element.
footerProps
DialogFooterProps
—
Properties forwarded to the footer element.
closeProps
DialogCloseProps
—
Properties forwarded to the close element.
fullscreen
boolean
undefined
The controlled fullscreen state of the dialog. Can be bound with `v-model:fullscreen`.
showClose
boolean
true
Whether show the close button in the header of the dialog.
showFullscreen
boolean
true
Whether show the fullscreen toggle button in the header of the dialog.
showCancel
boolean | 'onlyWarning'
'onlyWarning'
Whether to show the cancel button. When set to `onlyWarning`, the cancel button will only be shown when the dialog is an alert dialog with `alertType="warning"`. When set to `true`, the cancel button will always be shown.
cancelText
string
—
The text of the cancel button. This is used for accessibility purposes and will be rendered in the footer of the dialog if the `cancel` slot is not provided. Defaults to the localized `dialog.cancel` message from `ConfigProvider`.
showConfirm
boolean
—
Whether to show the confirm button when the dialog is an alert dialog. The default value is `true` when the dialog is an alert dialog.
confirmText
string
—
The text of the confirm button. This is used for accessibility purposes and will be rendered in the footer of the dialog if the `confirm` slot is not provided. Defaults to the localized `dialog.confirm` message from `ConfigProvider`.
overlayProps
DrawerOverlayProps
—
Properties forwarded to the overlay element.
titleProps
DialogTitleProps
—
Properties forwarded to the title element.
descriptionProps
DialogDescriptionProps
—
Properties forwarded to the description element.
fullscreenProps
DialogFullscreenProps
—
Properties forwarded to the fullscreen element.
cancelProps
DialogCancelProps
—
Properties forwarded to the cancel element.
confirmProps
DialogConfirmProps
—
Properties forwarded to the confirm element.
isAlert
boolean
false
Whether the dialog is an alert dialog. An alert dialog is a dialog that interrupts the user's workflow to communicate an important message and requires a response. When set to `true`, the dialog will have `role="alertdialog"` and will require a `DialogTitle` to be provided. This is used for accessibility purposes.
alertType
DialogAlertType
—
The alert type of the dialog, which determines the default icon and styles when the dialog is an alert dialog.
defaultFullscreen
boolean
false
The fullscreen state of the dialog when it is initially rendered. Use when you do not need to control its fullscreen state.
modal
import("../../types").ModalityTier
true
Modality tier. `true` blocks outside pointer events, `'trap-focus'` only traps focus, `false` keeps the surface non-modal.
snapPoint
DrawerSnapPoint | null
—
The controlled snap point. Can be bound with `v-model:snapPoint`.
defaultSnapPoint
DrawerSnapPoint | null
—
The snap point used when the drawer is initially rendered. Use when you do not need to control it. Defaults to the first entry of `snapPoints`.
snapToSequentialPoints
boolean
false
When `true`, snaps to the next sequential snap point (one step at a time). When `false`, snaps to the nearest snap point by distance.
closeThreshold
number
0.25
Close threshold as a fraction of the drawer size (0–1).
swipeDirection
SwipeDirection
—
The swipe direction that dismisses the drawer. Defaults to the direction opposite the drawer's entry edge (`side`).
fixed
boolean
—
Whether fixed.
dismissible
boolean
true
Whether dismissible.
nested
boolean
false
Whether nested.
side
Side
'bottom'
Direction.
noBodyStyles
boolean
—
When `true` the `body` doesn't get any styles assigned from the drawer
handleOnly
boolean
false
Whether handle only.
preventScrollRestoration
boolean
—
Whether prevent scroll restoration.
snapPoints
DrawerSnapPoint[]
—
Snap points used to position the drawer. Use numbers between 0 and 1 to represent fractions of the viewport height, numbers greater than 1 as pixel values, or strings in `px`/`rem` units.
handleProps
DrawerHandleProps
—
Properties forwarded to the handle element.
swipeable
boolean
false
Render the opt-in swipe-to-open area at the drawer's edge.
swipeAreaProps
DrawerSwipeAreaProps
—
Properties forwarded to the swipe area element.
Emits
Emit NameParametersDescription
cancel
MouseEvent
Event handler called when the dialog is requested to be canceled.
click
PointerEvent
Event handler called when the dialog trigger is activated.
fullscreen
MouseEvent
Event handler called when the fullscreen state of the dialog is requested to be toggled.
confirm
MouseEvent
Event handler called when the dialog is requested to be closed by confirming.
update:open
boolean
Event handler called when the open state of the dialog changes.
update:fullscreen
boolean
Event handler called when the fullscreen state of the dialog changes.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
interactOutside
PointerDownOutsideEvent | FocusOutsideEvent
Event handler called when an interaction happens outside the `DismissableLayer`. Specifically, when a `pointerdown` event happens outside or focus moves outside of it. Can be prevented.
openAutoFocus
Event
Event handler called when auto-focusing on open. Can be prevented.
closeAutoFocus
Event
Event handler called when auto-focusing on close. Can be prevented.
drag
number
Emitted while dragging with the live progress: 0 fully open, 1 closed.
release
boolean
Emitted when a drag gesture releases; `true` when the drawer stays open.
close
—
Emitted when close occurs.
update:snapPoint
DrawerSnapPoint | null
Emitted when the snap point value changes.
Slots
Slot NameParametersDescription
default
props: DialogCompactBaseSlotProps
Custom content for the default slot.
trigger
DialogCompactBaseSlotProps
Custom content for the trigger slot.
title
DialogCompactBaseSlotProps
Custom content for the title slot.
description
DialogCompactBaseSlotProps
Custom content for the description slot.
close
DialogCompactBaseSlotProps
Custom content for the close slot.
fullscreen
DialogCompactBaseSlotProps
Custom content for the fullscreen slot.
footer
DialogCompactBaseSlotProps
Custom content for the footer slot.
cancel
DialogCompactBaseSlotProps
Custom content for the cancel slot.
confirm
DialogCompactBaseSlotProps
Custom content for the confirm slot.

DrawerConfirm

4 Props1 Emits
Props
PropTypeDefaultDescription
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
confirm
MouseEvent
Event handler called when the dialog is requested to be closed by confirming.

DrawerContent

DrawerDescription

DrawerFooter

DrawerHandle

1 Props
Props
PropTypeDefaultDescription
preventCycle
boolean
—
Whether prevent cycle.

DrawerHeader

DrawerIndent

DrawerIndentBackground

DrawerOverlay

DrawerPopup

DrawerPortal

DrawerRoot

22 Props6 Emits1 Slots
Props
PropTypeDefaultDescription
open
boolean
undefined
The controlled open state of the dialog. Can be bound with `v-model:open`.
defaultOpen
boolean
false
The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
dir
Direction
—
The text direction of the dialog
draggable
boolean
false
Whether the dialog can be moved by dragging its header.
fullscreen
boolean
undefined
The controlled fullscreen state of the dialog. Can be bound with `v-model:fullscreen`.
isAlert
boolean
false
Whether the dialog is an alert dialog. An alert dialog is a dialog that interrupts the user's workflow to communicate an important message and requires a response. When set to `true`, the dialog will have `role="alertdialog"` and will require a `DialogTitle` to be provided. This is used for accessibility purposes.
alertType
DialogAlertType
—
The alert type of the dialog, which determines the default icon and styles when the dialog is an alert dialog.
defaultFullscreen
boolean
false
The fullscreen state of the dialog when it is initially rendered. Use when you do not need to control its fullscreen state.
modal
import("../../types").ModalityTier
true
Modality tier. `true` blocks outside pointer events, `'trap-focus'` only traps focus, `false` keeps the surface non-modal.
snapPoint
DrawerSnapPoint | null
—
The controlled snap point. Can be bound with `v-model:snapPoint`.
defaultSnapPoint
DrawerSnapPoint | null
—
The snap point used when the drawer is initially rendered. Use when you do not need to control it. Defaults to the first entry of `snapPoints`.
snapToSequentialPoints
boolean
false
When `true`, snaps to the next sequential snap point (one step at a time). When `false`, snaps to the nearest snap point by distance.
closeThreshold
number
0.25
Close threshold as a fraction of the drawer size (0–1).
swipeDirection
SwipeDirection
—
The swipe direction that dismisses the drawer. Defaults to the direction opposite the drawer's entry edge (`side`).
fixed
boolean
—
Whether fixed.
dismissible
boolean
true
Whether dismissible.
nested
boolean
false
Whether nested.
side
Side
'bottom'
Direction.
noBodyStyles
boolean
—
When `true` the `body` doesn't get any styles assigned from the drawer
handleOnly
boolean
false
Whether handle only.
preventScrollRestoration
boolean
—
Whether prevent scroll restoration.
snapPoints
DrawerSnapPoint[]
—
Snap points used to position the drawer. Use numbers between 0 and 1 to represent fractions of the viewport height, numbers greater than 1 as pixel values, or strings in `px`/`rem` units.
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the dialog changes.
update:fullscreen
boolean
Event handler called when the fullscreen state of the dialog changes.
drag
number
Emitted while dragging with the live progress: 0 fully open, 1 closed.
release
boolean
Emitted when a drag gesture releases; `true` when the drawer stays open.
close
—
Emitted when close occurs.
update:snapPoint
DrawerSnapPoint | null
Emitted when the snap point value changes.
Slots
Slot NameParametersDescription
default
{ open: boolean; close: () => void; }
Custom content for the default slot.

DrawerRootNested

DrawerSwipeArea

2 Props
Props
PropTypeDefaultDescription
swipeDirection
SwipeDirection
—
Override the swipe side that opens the drawer. Defaults to the opposite of the root swipe direction.
disabled
boolean
false
Disable swipe-to-open.

DrawerTitle

DrawerTrigger

4 Props1 Emits
Props
PropTypeDefaultDescription
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
click
PointerEvent
Event handler called when the dialog trigger is activated.

DrawerViewport

Notes

Architecture and benchmark differences

DrawerCompact owns the handle/swipe-area/overlay/popup/header/content/footer composition and the drag/snap state flow (via useDrawerSnapPoints and useSwipeDismiss), while every primitive stays style-free and only the UI wrapper injects the drawerVariants classes. The popup transform is CSS-variable driven — the gesture layer writes variables, never inline transforms — so snap settling, release bounce and dismissal all resolve through CSS transitions. This mirrors the Base UI Drawer model. Ant Design, Element Plus, Mantine and Naive UI ship a single styled drawer; a dedicated draggable panel with snapPoints is typically a separate library (vaul, Base UI Drawer). VeanUI exposes per-slot *Props, a size scale, and the snap/indent/drag/swipe model inline.

CapabilityVeanUIshadcn/ui + vaulreka-ui DrawerBase UIAnt DesignElement PlusMantine
Reuses dialog primitives✅✅✅✅———
Aria/styled split✅✅✅✅———
Drag-to-dismiss✅✅✅✅——✅
Snap points✅✅✅✅———
Swipe-to-open area✅—✅✅———
Page indent effect✅✅—✅———
Nested drawers✅✅✅✅———
Modality tiers✅—✅✅———
Sizes (6)✅——————

— = unsupported or a different interaction model.

Cautions

  • modal defaults to true; the panel teleports to document.body and body scroll is locked by the hide-others layer. The 'trap-focus' tier keeps outside pointer events alive but still traps focus.
  • side picks the anchored edge. Vertical sides (top/bottom) cap the panel at calc(100dvh - 2rem) so a long body scrolls inside the content slot instead of growing past the viewport; horizontal sides fill the viewport height and cap their width.
  • Drag-to-dismiss uses pointer capture; dismissible (default true) allows releasing past closeThreshold to close. Set false to force explicit actions. swipeDirection overrides the dismiss direction (defaults to the direction opposite the entry edge).
  • Horizontal sides ship vertical snap only in this release — snapPoints resolves against the vertical axis, so left/right snap behaviour is not yet supported.
  • snapPoints accepts fractions (0–1), pixel values (> 1) or CSS length strings; snapPoint tracks the current level and is bound with v-model:snap-point. The drawer opens at the first snap point and resets to it on close.
  • The drag handle is rendered only for side="bottom" in DrawerCompact; compose DrawerHandle manually for other sides.
  • handleOnly restricts dragging to the handle; fixed keeps the panel in place while inner content scrolls.
  • swipeable renders a gesture strip at the drawer’s edge; it is inert while the drawer is open.
  • nested renders via DrawerRootNested; each nested drawer coordinates drag and release with its parent.
  • Fullscreen defines the panel’s size and freezes its drag, matching how a dialog disables its draggable in fullscreen: a resting snap level below “fully open” would translate the panel back down and leave the half beyond its anchored edge off-screen, and a drag away from the edge would contradict the prop. Snapping and dragging resume when fullscreen is switched off; snapPoints stay configured throughout.
  • Because the drag is suspended, dismissal in fullscreen falls back to the explicit paths: the close button, Escape, and an outside press on a non-modal drawer. A modal fullscreen drawer with showClose={false} and dismissible={false} therefore has no way out — keep the close button (or modal={false}) if the user must be able to leave it.
  • The handle stops cycling snap levels while fullscreen, so it cannot rewrite snapPoint behind the scenes.
  • The drawer renders no fullscreen button of its own, so the dialog’s showFullscreen has no effect here — drive the state with v-model:fullscreen/defaultFullscreen, or render your own control inside the panel.
  • An uncontrolled fullscreen session does not survive a close: the drawer reopens at defaultFullscreen (matching the dialog’s reset).

Migrating from BottomSheet

v0.50.0 renamed the whole family — the name bottom-sheet is retired.

BeforeAfter
SBottomSheetSDrawer
BottomSheetRoot / BottomSheetRootNestedDrawerRoot / DrawerRootNested
BottomSheetPopup / BottomSheetOverlayDrawerPopup / DrawerOverlay
BottomSheetHandle / BottomSheetCompactDrawerHandle / DrawerCompact
BottomSheetTitle / BottomSheetDescriptionDrawerTitle / DrawerDescription
BottomSheetHeader / BottomSheetContent / BottomSheetFooterDrawerHeader / DrawerContent / DrawerFooter
BottomSheetTrigger / BottomSheetClose / BottomSheetCancel / BottomSheetConfirmDrawerTrigger / DrawerClose / DrawerCancel / DrawerConfirm
v-model:active-snap-pointv-model:snap-point
direction prop (Aria)side prop
@vean/aria/bottom-sheet@vean/aria/drawer
data-vean-bottom-sheet-*, soybean-bottom-sheet-draggingdata-vean-drawer-*, soybean-drawer-dragging
data-vean-bottom-sheet-scaleremoved with the scale-background engine (see below)

The old SDrawer (a dialog with a side) was renamed to SSheet. See Sheet for the side-panel API.

Migrating from the vaul-style engine

v0.50.0 replaced the vaul-derived engine with a Base UI-style one. The public surface changes:

BeforeAfter
shouldScaleBackground / setBackgroundColorOnScaleremoved. Wrap the page in DrawerIndent + DrawerIndentBackground inside DrawerRoot
fadeFromIndexremoved; the overlay fades continuously with the swipe progress
snapPoint defaulting to nulldefaults to the first entry of snapPoints (the drawer opens positioned at a snap point)
implicit drag direction from sidestill the default, overridable with swipeDirection
imperative transformsCSS variables (--vean-drawer-snap-point-offset, --vean-drawer-swipe-movement-x/y)
<!-- Before -->
<SBottomSheet v-model:open="open" should-scale-background>
  <div data-vean-drawer-scale>Page</div>
</SBottomSheet>

<!-- After -->
<SDrawer v-model:open="open">
  <DrawerIndent class="page-indent">Page</DrawerIndent>
  <template #trigger><SButton>Open</SButton></template>
</SDrawer>
<!-- Before -->
<SBottomSheet v-model:open="open" v-model:active-snap-point="snap" :snap-points="[0.5, 1]">
  <template #trigger><SButton>Open</SButton></template>
  Content
</SBottomSheet>

<!-- After -->
<SDrawer v-model:open="open" v-model:snap-point="snap" :snap-points="[0.5, 1]">
  <template #trigger><SButton>Open</SButton></template>
  Content
</SDrawer>

Roadmap

Horizontal snap points, on-device verification of the touch pipeline (iOS Safari / Android Chrome), and iOS virtual keyboard coordination.

FAQ

How do I anchor the drawer to a different edge?

Set side to top/bottom/left/right:

<SDrawer v-model:open="open" side="left" title="Filters">
  <template #trigger><SButton>Open</SButton></template>
  <div>Drawer content</div>
</SDrawer>

How do I enable snap points?

Pass an array of fractions, pixels or CSS lengths, and bind the active level:

<SDrawer v-model:open="open" v-model:snap-point="snapPoint" :snap-points="[0.4, 0.8, 1]" title="Filters">
  <template #trigger><SButton>Open</SButton></template>
  <div>Drawer content</div>
</SDrawer>

How do I open the drawer with a swipe gesture?

Set swipeable. An edge strip is rendered at the panel’s side and swipes in the opposite direction:

<SDrawer v-model:open="open" swipeable title="Details">
  <template #trigger><SButton>Open</SButton></template>
  <div>Drawer content</div>
</SDrawer>

How do I disable drag-to-dismiss?

Set dismissible={false} to require an explicit action:

<SDrawer :dismissible="false" title="Confirm">
  <template #trigger><SButton>Open</SButton></template>
  <div>Drawer content</div>
</SDrawer>

How do I restrict dragging to the handle?

Set handle-only:

<SDrawer handle-only title="Details">
  <template #trigger><SButton>Open</SButton></template>
  <div>Drawer content</div>
</SDrawer>

How do I build a non-modal side panel that still traps focus?

Use the 'trap-focus' tier:

<SDrawer v-model:open="open" modal="trap-focus" title="Inspector">
  <template #trigger><SButton>Open</SButton></template>
  <div>Drawer content</div>
</SDrawer>

How do I make the drawer fullscreen?

Bind v-model:fullscreen, or let it start fullscreen with default-fullscreen. The panel grows to the viewport from its side edge and stops responding to drags, so snapping and dragging resume only once you switch fullscreen off:

<SDrawer v-model:open="open" v-model:fullscreen="fullscreen" :snap-points="[0.6, 1]" title="Details">
  <template #trigger><SButton>Open</SButton></template>
  <div>Drawer content</div>
</SDrawer>

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.0

2026-10-02

Compare release

Fix

settle controlled snap points and remove first-open position flash

Scope: drawerAuthors: soybeanjsView commited96b

Fix

repair gesture release velocity, pinch leak and uncontrolled swipe-area open

Scope: drawerAuthors: soybeanjsView commit135ae

Fix

re-measure the popup box when the viewport changes

Scope: drawerAuthors: soybeanjsView commit4f32c

Fix

keep the panel inside the viewport and its largest snap point

Scope: drawerAuthors: soybeanjsView commit0dc2a

Fix

wire the fullscreen state to the panel

Scope: drawerAuthors: soybeanjsView commitaa4b0

Fix

suspend snapping while the drawer is fullscreen

Scope: drawerAuthors: soybeanjsView commit716ac

Fix

freeze the drag gesture while the drawer is fullscreen

Scope: drawerAuthors: soybeanjsView commit336d1

Fix

keep the content height after leaving fullscreen

Scope: drawerAuthors: soybeanjsView commit44693

Refactor

rename BottomSheet→Drawer, split Sheet, add swipe-dismiss & side variants

Scope: drawerAuthors: soybeanjsView commitf017c

Refactor

port Base UI gesture model and fix six interaction bugs

Scope: drawerAuthors: soybeanjsView commit067c9

Docs

add Base UI model refactor plan and link from v0.50.0

Scope: drawerAuthors: soybeanjsView commit16acf

Docs

record the iOS verification of the toolbar fix

Scope: drawerAuthors: soybeanjsView commit1f9bc

Docs

add a form example covering the on-screen keyboard

Scope: drawerAuthors: soybeanjsView commitbbf70

Docs

sync the generated skill with the fullscreen contract

Scope: drawerAuthors: soybeanjsView commit32578

Chore

port Base UI drawer contracts to browser e2e and settle D4.3

Scope: drawerAuthors: soybeanjsView commit7bdea

Fix

wire the fullscreen state to the panel

Scope: drawerAuthors: soybeanjsView commitaa4b0

Fix

suspend snapping while the drawer is fullscreen

Scope: drawerAuthors: soybeanjsView commit716ac

Fix

freeze the drag gesture while the drawer is fullscreen

Scope: drawerAuthors: soybeanjsView commit336d1

Fix

keep the content height after leaving fullscreen

Scope: drawerAuthors: soybeanjsView commit44693

Docs

sync the generated skill with the fullscreen contract

Scope: drawerAuthors: soybeanjsView commit32578

Fix

settle controlled snap points and remove first-open position flash

Scope: drawerAuthors: soybeanjsView commited96b

Fix

repair gesture release velocity, pinch leak and uncontrolled swipe-area open

Scope: drawerAuthors: soybeanjsView commit135ae

Fix

re-measure the popup box when the viewport changes

Scope: drawerAuthors: soybeanjsView commit4f32c

Fix

keep the panel inside the viewport and its largest snap point

Scope: drawerAuthors: soybeanjsView commit0dc2a

Refactor

rename BottomSheet→Drawer, split Sheet, add swipe-dismiss & side variants

Scope: drawerAuthors: soybeanjsView commitf017c

Refactor

port Base UI gesture model and fix six interaction bugs

Scope: drawerAuthors: soybeanjsView commit067c9

Docs

add Base UI model refactor plan and link from v0.50.0

Scope: drawerAuthors: soybeanjsView commit16acf

Docs

record the iOS verification of the toolbar fix

Scope: drawerAuthors: soybeanjsView commit1f9bc

Docs

add a form example covering the on-screen keyboard

Scope: drawerAuthors: soybeanjsView commitbbf70

Chore

port Base UI drawer contracts to browser e2e and settle D4.3

Scope: drawerAuthors: soybeanjsView commit7bdea

v0.31.0

2026-08-31

Compare release

Refactor

wrap Dialog chrome as domain primitives

Scope: bottom-sheetAuthors: soybeanfe, cursoragentView commitddd66

v0.20.0

2026-05-12

Compare release

Fix

simplify variant merging logic and remove unused slot

Scope: bottom-sheetAuthors: soybeanjsView commite96e7

Fix

simplify variant assignment in computed property

Scope: drawerAuthors: soybeanjsView commitb55f5

v0.19.0

2026-05-11

Compare release

Fix

improve fadeFromIndex and snapPoints logic

Scope: bottom-sheetAuthors: soybeanfeView commit76d82

v0.15.4

2026-04-30

Compare release

Feature

Implement BottomSheet component

Scope: componentsAuthors: soybeanjs, CopilotKitView commitfb274

v0.0.10

2026-01-07

Compare release

Refactor

update drawer component structure and styling, replacing drawerContentVariants with drawerVariants for improved UI management

Scope: drawerAuthors: soybeanjsView commitcfb41

v0.0.2

2025-11-18

Compare release

Feature

add new bottom sheet component with size variants and default settings

Scope: bottom-sheetAuthors: soybeanjsView commitfa3f6

Feature

introduce new drawer component with side and scroll variants, update dialog examples to use pure button variant

Scope: drawerAuthors: soybeanjsView commitb2042

Feature

add scrollable functionality to drawer component and update related styles

Scope: drawerAuthors: soybeanjsView commite199f

Fix

update DialogClose class binding for closable state

Scope: drawerAuthors: soybeanjsView commit2958b

Optimization

update DialogClose slot name from closeIcon to close for consistency

Scope: drawerAuthors: soybeanjsView commitc72e3

Feature

add new bottom sheet component with size variants and default settings

Scope: bottom-sheetAuthors: soybeanjsView commitfa3f6

Feature

add default prop for background scaling

Scope: drawerAuthors: soybeanjsView commit1fe4b

Feature

introduce new drawer component with side and scroll variants, update dialog examples to use pure button variant

Scope: drawerAuthors: soybeanjsView commitb2042

Feature

add scrollable functionality to drawer component and update related styles

Scope: drawerAuthors: soybeanjsView commite199f

Fix

update DialogClose class binding for closable state

Scope: drawerAuthors: soybeanjsView commit2958b

Optimization

update DialogClose slot name from closeIcon to close for consistency

Scope: drawerAuthors: soybeanjsView commitc72e3

Feature

add default prop for background scaling

Scope: drawerAuthors: soybeanjsView commit1fe4b