Usage
import { Drawer } from "@voila.dev/ui/drawer";<Drawer.Root direction="right">
<Drawer.Trigger asChild>
<Button variant="outline">View project</Button>
</Drawer.Trigger>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Launch review — Saturday</Drawer.Title>
<Drawer.Description>Kickoff call · Zoom, 14:00.</Drawer.Description>
</Drawer.Header>
<Drawer.Footer>
<Button>Apply to this project</Button>
</Drawer.Footer>
</Drawer.Content>
</Drawer.Root>A panel you can throw. Built on Vaul, so it
drags with momentum and snaps like a native sheet — which is why this one uses
asChild where the rest of the kit uses render. Choose it over
Sheet when the gesture is part of the point, which on touch it
usually is. Choose Sheet when the panel is desktop furniture that happens to
slide.
Recipes
direction sets the edge. Only top and bottom drawers drag, so
showHandle — the grab bar — is meaningful there and noise on the sides;
showCloseButton exists for exactly that reason, giving left/right drawers
a way out that a handle would otherwise have provided.
overlayClassName styles the backdrop, className the panel. They are separate
props because dimming the page and shaping the sheet are different decisions.
API
Drawer.Root
| Prop | Type | Default | |
|---|---|---|---|
activeSnapPoint | string | number | null | — | |
autoFocus | boolean | — | |
children | ReactNode | — | |
closeThreshold | number | — | Number between 0 and 1 that determines when the drawer should be closed. Example: threshold of 0.5 would close the drawer if the user swiped for 50% of the height of the drawer or more. |
container | HTMLElement | null | — | |
defaultOpen | boolean | — | Opened by default, skips initial enter animation. Still reacts to open state changes |
direction | "bottom" | "left" | "right" | "top" | — | Direction of the drawer. Can be top or bottom, left, right. |
disablePreventScroll | boolean | — | When set to true prevents scrolling on the document body on mount, and restores it on unmount. |
dismissible | boolean | — | When false dragging, clicking outside, pressing esc, etc. will not close the drawer.
Use this in comination with the open prop, otherwise you won't be able to open/close the drawer. |
fadeFromIndex | number | — | Index of a snapPoint from which the overlay fade should be applied. Defaults to the last snap point. |
fixed | boolean | — | When true, don't move the drawer upwards if there's space, but rather only change it's height so it's fully scrollable when the keyboard is open |
handleOnly | boolean | — | When true only allows the drawer to be dragged by the <Drawer.Handle /> component. |
modal | boolean | — | When false it allows to interact with elements outside of the drawer without closing it. |
nested | boolean | — | |
noBodyStyles | boolean | — | When true the body doesn't get any styles assigned from Vaul |
onAnimationEnd | ((open: boolean) => void) | — | Gets triggered after the open or close animation ends, it receives an open argument with the open state of the drawer by the time the function was triggered.
Useful to revert any state changes for example. |
onClose | (() => void) | — | |
onDrag | ((event: PointerEvent<HTMLDivElement>, percentageDragged: number) => void) | — | |
onOpenChange | ((open: boolean) => void) | — | |
onRelease | ((event: PointerEvent<HTMLDivElement>, open: boolean) => void) | — | |
open | boolean | — | |
preventScrollRestoration | boolean | — | |
repositionInputs | boolean | — | When true Vaul will reposition inputs rather than scroll then into view if the keyboard is in the way.
Setting it to false will fall back to the default browser behavior. |
scrollLockTimeout | number | — | Duration for which the drawer is not draggable after scrolling content inside of the drawer. |
setActiveSnapPoint | ((snapPoint: string | number | null) => void) | — | |
setBackgroundColorOnScale | boolean | — | When false we don't change body's background color when the drawer is open. |
shouldScaleBackground | boolean | — | |
snapPoints | (string | number)[] | — | Array of numbers from 0 to 100 that corresponds to % of the screen a given snap point should take up.
Should go from least visible. Example [0.2, 0.5, 0.8].
You can also use px values, which doesn't take screen height into account. |
snapToSequentialPoint | boolean | — | Disabled velocity based swiping for snap points. This means that a snap point won't be skipped even if the velocity is high enough. Useful if each snap point in a drawer is equally important. |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-root.tsx.
The undescribed props here are Vaul's own —
snapPoints, modal, nested and the rest — and cannot be annotated from this
repo. Vaul's documentation covers them.
Drawer.Close
| Prop | Type | Default | |
|---|---|---|---|
asChild | boolean | — |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-close.tsx.
Drawer.Content
| Prop | Type | Default | |
|---|---|---|---|
closeButtonLabel | string | "Close" | Accessible name for that X. This package ships no translations. |
overlayClassName | string | — | Classes for the backdrop behind the panel. className styles the panel itself. |
showCloseButton | boolean | true | Renders an X button on left/right drawers, which have no grab handle. |
showHandle | boolean | true | Draws the grab bar. Only meaningful on top/bottom drawers, which drag. |
asChild | boolean | — | |
forceMount | true | — | Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. |
onCloseAutoFocus | ((event: Event) => void) | — | Event handler called when auto-focusing on close. Can be prevented. |
onEscapeKeyDown | ((event: KeyboardEvent) => void) | — | Event handler called when the escape key is down. Can be prevented. |
onFocusOutside | ((event: FocusOutsideEvent) => void) | — | Event handler called when the focus moves outside of the DismissableLayer.
Can be prevented. |
onInteractOutside | ((event: FocusOutsideEvent | PointerDownOutsideEvent) => void) | — | 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. |
onOpenAutoFocus | ((event: Event) => void) | — | Event handler called when auto-focusing on open. Can be prevented. |
onPointerDownOutside | ((event: PointerDownOutsideEvent) => void) | — | Event handler called when the a pointerdown event happens outside of the DismissableLayer.
Can be prevented. |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-content.tsx.
Drawer.Description
| Prop | Type | Default | |
|---|---|---|---|
asChild | boolean | — |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-description.tsx.
Drawer.Footer
| Prop | Type | Default | |
|---|---|---|---|
render | ComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Plus every <div> prop. Source: drawer/components/drawer-footer.tsx.
Drawer.Handle
Plus every <div> prop. Source: drawer/components/drawer-handle.tsx.
Drawer.Header
| Prop | Type | Default | |
|---|---|---|---|
render | ComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Plus every <div> prop. Source: drawer/components/drawer-header.tsx.
Drawer.Overlay
| Prop | Type | Default | |
|---|---|---|---|
asChild | boolean | — | |
forceMount | true | — | Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-overlay.tsx.
Drawer.Portal
| Prop | Type | Default | |
|---|---|---|---|
children | ReactNode | — | |
container | DocumentFragment | Element | null | — | Specify a container element to portal the content into. |
forceMount | true | — | Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-portal.tsx.
Drawer.Title
| Prop | Type | Default | |
|---|---|---|---|
asChild | boolean | — |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-title.tsx.
Drawer.Trigger
| Prop | Type | Default | |
|---|---|---|---|
asChild | boolean | — |
Plus the DOM props of the element it renders. Source: drawer/components/drawer-trigger.tsx.