Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/drawer.jsonUsage
Pass trigger, title, description, footer, and body children as props — no manual slot composition needed.
TSImport
import { Drawer } from "@/components/ui/drawer";TSExample
import { Button } from "@/components/ui/button";
import { Drawer } from "@/components/ui/drawer";
export function Example() {
return (
<Drawer
trigger={<Button variant="outline">Open</Button>}
title="Are you sure?"
description="This action cannot be undone."
closeLabel="Cancel"
direction="right"
>
{/* body content */}
</Drawer>
);
}Composition
Anatomy of the Drawer primitive.
// Flat one-liner — covers most use cases
<Drawer
trigger={<Button>Open</Button>}
title="Title"
description="Optional subtitle."
footer={<Button className="w-full">Confirm</Button>}
closeLabel="Cancel" // convenience close button in footer
direction="right" // default for flat API
isFloat // default true — card-style floating panel
notch // default true — drag-handle pill
open / onOpenChange // controlled mode; omit trigger when using these
contentClassName // className forwarded to DrawerContent
bodyClassName // className forwarded to DrawerBody
>
{body content}
</Drawer>
// Escape hatch — slot exports remain available for complex compositions
import {
DrawerRoot, DrawerTrigger, DrawerContent,
DrawerHeader, DrawerTitle, DrawerDescription,
DrawerBody, DrawerFooter, DrawerClose,
} from "@/components/ui/drawer";Basic
A right-side drawer triggered by a button. Pass trigger, title, description, footer, and body children — no manual slot composition needed.
Side
Pass `direction` to slide in from any edge. The radio group lets you pick top, bottom, left, or right at runtime.
Inset
Set `isFloat={false}` for an edge-flush drawer with no outer margin or rounded outer corners — the drawer runs all the way to the screen edge.
Controlled
Drive open state with `useState`. Pass `open` and `onOpenChange`. Omit `trigger` and handle the open button yourself.
Notchless
Set `notch={false}` to hide the drag-handle pill. Uses a bottom drawer here to make the missing notch visible — the prop works on any direction.
Sticky header & footer
Body content scrolls inside DrawerBody (flex-1, overflow-y-auto) while the header and footer stay pinned. Pass long content as children.
API Reference
All props on the flat Drawer component.
Drawer
| Prop | Type | Default | Description |
|---|---|---|---|
trigger | ReactNode | — | Trigger element rendered inside DrawerTrigger with asChild. Omit when using controlled mode. |
title | ReactNode | — | Drawer title. Omitting title and description skips DrawerHeader. |
description | ReactNode | — | Optional subtitle rendered below the title in muted text. |
children | ReactNode | — | Scrollable body content inside DrawerBody. |
footer | ReactNode | — | Footer content. Omitting footer and closeLabel skips DrawerFooter. |
closeLabel | ReactNode | — | Convenience: renders an outline close button in the footer via DrawerClose. |
direction | "top" | "bottom" | "left" | "right" | "right" | Which edge the drawer slides in from. |
isFloat | boolean | true | Floating card style with inset margin and rounded corners. Set false for edge-flush. |
notch | boolean | true | Shows or hides the drag-handle pill. Only visible on top/bottom drawers. |
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Callback fired when the open state changes. |
dismissible | boolean | true | Whether clicking the overlay closes the drawer. |
modal | boolean | true | When false, background content remains interactive. |
contentClassName | string | — | Extra className forwarded to DrawerContent. |
bodyClassName | string | — | Extra className forwarded to DrawerBody. |
Escape-hatch slot exports
| Prop | Type | Default | Description |
|---|---|---|---|
DrawerRoot | vaul Root | — | Raw vaul drawer root (replaces old Drawer slot export). Accepts all vaul Root props. |
DrawerContent | component | — | isFloat (default true), notch (default true), plus all vaul Content props. |
DrawerBody | component | — | flex-1 overflow-y-auto scrollable area. Accepts className. |
DrawerHeader / DrawerFooter | component | — | Layout wrappers. Accept className and children. |
DrawerTitle / DrawerDescription | vaul primitives | — | Emit data-slot markers used by CSS variant hooks. |
DrawerTrigger / DrawerClose | vaul primitives | — | Use asChild to wrap your own Button. |