A touch-friendly panel that slides in from any edge of the screen, built on Vaul.
A composable drawer component built on Vaul. It slides in from the bottom, top, left, or right edge of the viewport with a drag-to-dismiss gesture. A bottom drawer automatically renders a drag handle indicator.
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
import { Button } from "@/components/ui/button"
export default function DrawerDemo() {
return (
<Drawer>
<DrawerTrigger asChild>
<Button variant="outline">Open Drawer</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Move Goal</DrawerTitle>
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
</DrawerHeader>
<div className="p-4">
<div className="flex items-center justify-center text-4xl font-bold">
350
</div>
<p className="text-center text-sm text-muted-foreground">calories/day</p>
</div>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose asChild>
<Button variant="outline">Cancel</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
)
}
import {
Drawer,
DrawerTrigger,
DrawerContent,
DrawerHeader,
DrawerFooter,
DrawerTitle,
DrawerDescription,
DrawerClose,
DrawerOverlay,
DrawerPortal,
} from "@/components/ui/drawer"<Drawer>
<DrawerTrigger>Open</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Title</DrawerTitle>
<DrawerDescription>Description text.</DrawerDescription>
</DrawerHeader>
{/* Body content */}
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose>Cancel</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>The default direction. A drag handle is rendered automatically at the top.
<Drawer>
<DrawerTrigger render={<Button />}>Open Drawer</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Notifications</DrawerTitle>
<DrawerDescription>You have 3 unread messages.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button>Mark all as read</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>Pass direction="right" to the root to slide in from the right. Constrained to sm:max-w-sm.
<Drawer direction="right">
<DrawerTrigger render={<Button />}>Settings</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Settings</DrawerTitle>
<DrawerDescription>Manage your preferences.</DrawerDescription>
</DrawerHeader>
<div className="p-4">
<p>Settings content goes here.</p>
</div>
</DrawerContent>
</Drawer>Pass direction="left" for navigation-style drawers.
<Drawer direction="left">
<DrawerTrigger render={<Button variant="outline" />}>Menu</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Navigation</DrawerTitle>
</DrawerHeader>
<nav className="flex flex-col gap-2 p-4">
<a href="/dashboard">Dashboard</a>
<a href="/settings">Settings</a>
</nav>
</DrawerContent>
</Drawer>The root component that manages open/close state and slide direction. Wraps Vaul's Drawer.Root.
| Prop | Type | Default | Description |
|---|---|---|---|
direction | "bottom" | "top" | "left" | "right" | "bottom" | The edge the drawer slides in from. |
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Callback when the open state changes. |
children | ReactNode | — |
The element that opens the drawer when clicked. Wraps Vaul's Drawer.Trigger.
| Prop | Type | Default |
|---|---|---|
className | string | — |
children | ReactNode | — |
The sliding panel rendered in a portal with an overlay. Adapts its position, rounding, and border based on the drawer direction.
| Prop | Type | Default |
|---|---|---|
className | string | — |
children | ReactNode | — |
A <div> for the title and description. Centered for top/bottom drawers, left-aligned for side drawers on md+.
| Prop | Type | Default |
|---|---|---|
className | string | — |
children | ReactNode | — |
A <div> pinned to the bottom of the drawer via mt-auto.
| Prop | Type | Default |
|---|---|---|
className | string | — |
children | ReactNode | — |
The drawer heading. Wraps Vaul's Drawer.Title.
| Prop | Type | Default |
|---|---|---|
className | string | — |
children | ReactNode | — |
Secondary text below the title. Wraps Vaul's Drawer.Description.
| Prop | Type | Default |
|---|---|---|
className | string | — |
children | ReactNode | — |
An element that closes the drawer when clicked. Wraps Vaul's Drawer.Close.
| Prop | Type | Default |
|---|---|---|
className | string | — |
children | ReactNode | — |
The backdrop behind the drawer. Renders with a blurred, semi-transparent background.
| Prop | Type | Default |
|---|---|---|
className | string | — |
Portals the drawer content to the end of document.body. Wraps Vaul's Drawer.Portal.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | — |