Drawer
A draggable, dismissible panel that slides in from any edge of the screen.
Default
tsx
import { Button, CloseButton, Drawer } from "@hummingbirdui/react";
export default function DrawerDefault() {
return (
<Drawer>
<Drawer.Trigger asChild>
<Button variant="outline">Open drawer</Button>
</Drawer.Trigger>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Drawer title</Drawer.Title>
<Drawer.Close asChild>
<CloseButton />
</Drawer.Close>
</Drawer.Header>
<Drawer.Body>
<Drawer.Description>
Drag it down, click the backdrop, press Escape, or use the close
button to dismiss it.
</Drawer.Description>
</Drawer.Body>
</Drawer.Content>
</Drawer>
);
}Direction
Passing direction ("top" | "right" | "bottom" | "left") to Drawer sets the edge the panel slides from.
tsx
import { Button, CloseButton, Drawer } from "@hummingbirdui/react";
const directions = ["top", "right", "bottom", "left"] as const;
export default function DrawerDirection() {
return (
<div className="flex flex-wrap gap-2 justify-center">
{directions.map((direction) => (
<Drawer key={direction} direction={direction}>
<Drawer.Trigger asChild>
<Button variant="outline" className="capitalize">
{direction}
</Button>
</Drawer.Trigger>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title className="capitalize">
{direction} drawer
</Drawer.Title>
<Drawer.Close asChild>
<CloseButton />
</Drawer.Close>
</Drawer.Header>
<Drawer.Body>
<Drawer.Description>
Slides in from the {direction} edge.
</Drawer.Description>
</Drawer.Body>
</Drawer.Content>
</Drawer>
))}
</div>
);
}Without overlay
Setting overlay={false} on Drawer.Content renders the panel without the backdrop.
tsx
import { Button, CloseButton, Drawer } from "@hummingbirdui/react";
export default function DrawerWithoutOverlay() {
return (
<Drawer direction="right">
<Drawer.Trigger asChild>
<Button variant="outline">Open without overlay</Button>
</Drawer.Trigger>
<Drawer.Content overlay={false}>
<Drawer.Header>
<Drawer.Title>No backdrop</Drawer.Title>
<Drawer.Close asChild>
<CloseButton />
</Drawer.Close>
</Drawer.Header>
<Drawer.Body>
<Drawer.Description>
Setting <code>overlay={false}</code> hides the backdrop so
the page behind stays visible.
</Drawer.Description>
</Drawer.Body>
</Drawer.Content>
</Drawer>
);
}Scrollable body
Drawer.Body grows to fill the panel and scrolls its own overflow while the header stays pinned.
tsx
import { Button, CloseButton, Drawer } from "@hummingbirdui/react";
export default function DrawerScrollable() {
return (
<Drawer direction="right">
<Drawer.Trigger asChild>
<Button variant="outline">Open long drawer</Button>
</Drawer.Trigger>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Terms of service</Drawer.Title>
<Drawer.Close asChild>
<CloseButton />
</Drawer.Close>
</Drawer.Header>
<Drawer.Body>
<p>Scroll to read all of the content below.</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum
nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi.
Nulla quis sem at nibh elementum imperdiet.
</p>
<p>
Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue
semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla.
</p>
<p>
Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Curabitur sodales ligula in libero.
</p>
<p>
Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh.
Aenean quam. In scelerisque sem at dolor. Maecenas mattis.
</p>
</Drawer.Body>
</Drawer.Content>
</Drawer>
);
}API Reference
Built on Vaul. Each part forwards all props to its Vaul counterpart, except Drawer.Header and Drawer.Body, which are Hummingbird-specific layout parts rendered as plain div elements.
Drawer
Contains all the parts of a drawer.
| Prop | Type | Default |
|---|---|---|
defaultOpen | boolean | false |
open | boolean | — |
onOpenChange | function | — |
modal | boolean | true |
container | HTMLElement | document.body |
direction | enum | "bottom" |
onAnimationEnd | function | — |
dismissible | boolean | true |
handleOnly | boolean | false |
repositionInputs | boolean | true |
snapPoints | array | — |
activeSnapPoint | number | string | null | — |
setActiveSnapPoint | function | — |
fadeFromIndex | number | — |
snapToSequentialPoint | boolean | false |
Drawer.Trigger
The button that opens the drawer.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | — |
| Data attribute | Values |
|---|---|
[data-state] | "open" | "closed" |
Drawer.Portal
When used, portals your overlay and content parts into the body. Drawer.Content renders this part automatically, so you rarely need to use it directly.
| Prop | Type | Default |
|---|---|---|
forceMount | boolean | — |
container | HTMLElement | document.body |
Drawer.Overlay
A layer that covers the inert portion of the view when the drawer is open. Drawer.Content renders this part automatically while overlay is true.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
forceMount | boolean | — |
className | string | — |
| Data attribute | Values |
|---|---|
[data-state] | "open" | "closed" |
Drawer.Content
Contains content to be rendered in the open drawer. Always renders its own Drawer.Portal, and shows a drag handle when direction is "bottom".
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
forceMount | boolean | — |
onOpenAutoFocus | function | — |
onCloseAutoFocus | function | — |
onEscapeKeyDown | function | — |
onPointerDownOutside | function | — |
onInteractOutside | function | — |
overlay | boolean | true |
className | string | — |
| Data attribute | Values |
|---|---|
[data-state] | "open" | "closed" |
[data-vaul-drawer-direction] | "top" | "right" | "bottom" | "left" |
Drawer.Header
Hummingbird-specific layout part. Renders a div with the offcanvas-header class for the top area of the drawer.
Drawer.Title
An accessible title to be announced when the drawer is opened. Renders an h6 element by default.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | — |
Drawer.Description
An optional accessible description to be announced when the drawer is opened.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | — |
Drawer.Body
Hummingbird-specific layout part. Renders a div with the offcanvas-body class that grows to fill the panel and scrolls its own overflow.
Drawer.Close
The button that closes the drawer.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | — |
Styling
Hummingbird React drawer is styled entirely through Hummingbird's utility classes and CSS variables.
- See the full list of available drawer classes in the Class overview.
- Visit the CSS Variables documentation to explore all available variables.