Components

Drawer

A React drawer that slides in from any edge with a Liquid Glass surface and swipe dismissal.

Drawer is an edge-aligned panel with swipe dismissal. It renders the portal, backdrop, popup, title, description, optional body, and a custom action area internally, with optional snap points.

Unlike the centered Dialog, Drawer slides in from an edge of the screen, which makes it a good fit for mobile settings panels, filters, and side navigation.

Basic example

The drawer opens from the bottom by default. open controls visibility and footer holds your own buttons; buttons do not close the drawer automatically, so update open yourself as the example does.

Side panels

direction accepts four values: down slides in from the bottom, up from the top, and left and right from the matching side. It defaults to down, and the component adjusts the popup position, corner radii, enter animation, and swipe dismissal direction together.

Gesture dismissal

On touch screens, drag the drawer in the direction set by direction to dismiss it. On desktop, the backdrop, Escape key, and action buttons remain available.

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

Snap points

snapPoints, defaultSnapPoint, snapPoint, onSnapPointChange, and snapToSequentialPoints configure snap heights and can make a bottom or top drawer settle between preset heights.

Backdrop dismissal

disablePointerDismissal prevents the backdrop from closing the drawer while Escape and the action buttons still work. Use it for flows that may contain unsaved work.

Accessibility

Drawer uses the same dialog semantics as Dialog: focus moves into the panel, stays trapped while it is open, and returns to the trigger when it closes. title names the panel and description describes it.

Escape, the backdrop, and the swipe gesture close it; use disablePointerDismissal and a visible cancel action when dismissal could lose work. Keep swipe gestures away from horizontally scrollable content. See the accessibility guide for overlay focus rules.

API reference

PropTypeDefaultDescription
titleReactNode—Drawer heading. Required.
descriptionReactNode—Supporting copy under the title.
childrenReactNode—Body content between the description and the action area.
footerReactNode—Bottom action area that can hold any number of controls.
direction"down" | "up" | "left" | "right""down"Edge the drawer slides in from, also used as the swipe dismissal direction.
openboolean—Controlled open state.
defaultOpenbooleanfalseInitial open state when uncontrolled.
onOpenChange(open: boolean, details) => void—Called when the drawer opens or closes.
onOpenChangeComplete(open: boolean) => void—Called after the open or close animation finishes.
modalboolean | "trap-focus"trueControls focus trapping and page scroll locking.
disablePointerDismissalbooleanfalsePrevents the backdrop from closing the drawer.
actionsRefRefObject<Actions | null>—Imperative close and unmount actions.
handleDrawerHandle—Associates the drawer with external triggers.
triggerIdstring | null—ID of the trigger associated with the drawer.
defaultTriggerIdstring | null—ID of the trigger used for an initially open drawer.
snapPointsDrawerSnapPoint[]—Snap heights, as viewport fractions, pixel numbers, or px/rem strings.
snapToSequentialPointsbooleanfalseUses drag distance instead of velocity to choose the next snap point.
snapPointDrawerSnapPoint | null—Controlled active snap point.
defaultSnapPointDrawerSnapPoint | null—Initial snap point when uncontrolled.
onSnapPointChange(snapPoint: DrawerSnapPoint | null, details) => void—Called when the active snap point changes.
classNamestring—Tailwind classes merged into the popup.
styleCSSProperties—Inline styles merged into the same element as className.
ui{ backdrop?: ClassValue; viewport?: ClassValue; popup?: ClassValue; glass?: ClassValue; overlay?: ClassValue; content?: ClassValue; title?: ClassValue; description?: ClassValue; body?: ClassValue; footer?: ClassValue }—Tailwind classes for internal slots, keyed by data-slot.
AttributeDescription
data-openPresent when the drawer is open.
data-closedPresent when the drawer is closed.
data-starting-stylePresent when the drawer begins animating in.
data-ending-stylePresent when the drawer is animating out.
data-expandedPresent when the drawer is at the expanded snap point.
data-nestedPresent when the drawer is nested within another drawer.
data-nested-drawer-openPresent when another drawer is open inside this one.
data-nested-drawer-swipingPresent while a nested drawer is being swiped.
data-swipe-dismissPresent when the drawer is dismissed by a swipe.
data-swipe-directionIndicates the swipe direction (up, down, left, or right).
data-swipingPresent while the drawer is being swiped.
data-slotMarks internal parts (backdrop, viewport, popup, glass, overlay, content, title, description, body, footer) for styling.

Theming

The component uses the shared glass material. Tune shared --ui-glass-* tokens on a parent, use className for layout, and use ui for internal slots keyed by data-slot. Component-specific values live in src/theme/drawer.ts. See the theming guide for token layers and presets.

  • Dialog — For centered modal content.
  • Alert Dialog — For explicit destructive decisions.
  • Popover — For non-modal contextual panels.