A customizable slide-out panel component built on top of Vaul with support for multiple positions, sizes, and behaviors.
Overview
The Drawer component provides an elegant solution for displaying secondary content and actions without disrupting the main user flow, making it ideal for mobile navigation, form overlays, and contextual panels. It supports gesture-driven interactions and multiple positioning options, enhancing user experience with smooth animations and intuitive controls. Essential for creating modern, mobile-first interfaces that feel natural and responsive.
Installation
pnpm dlx shadcn@latest add https://deltacomponents.dev/r/drawer.json
Usage
import {
Drawer,
DrawerBody,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/registry/components/drawer"
export function Component() {
return (
<Drawer>
<DrawerTrigger>Open Drawer</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Drawer Title</DrawerTitle>
<DrawerDescription>Drawer description</DrawerDescription>
</DrawerHeader>
<DrawerBody>Your content here</DrawerBody>
<DrawerFooter>
<DrawerClose>Close</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
)
}
Left/Right Drawer Positioning
For proper left and right drawer animations, use both the direction
prop on the Drawer root and the position
prop on DrawerContent:
// Left drawer
<Drawer direction="left">
<DrawerContent
position="left"
className="fixed inset-y-0 left-0 h-full w-3/4 sm:max-w-sm"
>
{/* content */}
</DrawerContent>
</Drawer>
// Right drawer
<Drawer direction="right">
<DrawerContent
position="right"
className="fixed inset-y-0 right-0 h-full w-3/4 sm:max-w-sm"
>
{/* content */}
</DrawerContent>
</Drawer>
API Reference
Props
Drawer
Prop | Type | Default | Description |
---|---|---|---|
shouldScaleBackground | boolean | true | Whether to scale the background when open |
direction | "top" | "bottom" | "left" | "right" | "bottom" | Position of the drawer |
scrollable | boolean | false | Enable scrollable content |
size | "sm" | "default" | "lg" | "xl" | "full" | "default" | Size variant |
closeOnClickOutside | boolean | true | Close when clicking outside |
hasOverlay | boolean | true | Show overlay background |
container | HTMLElement | null | undefined | Portal container element |
nested | boolean | false | Support for nested drawers |
DrawerContent
Prop | Type | Default | Description |
---|---|---|---|
position | "top" | "bottom" | "left" | "right" | "bottom" | Content position |
size | "sm" | "default" | "lg" | "xl" | "full" | "default" | Content size |
scrollable | boolean | false | Enable content scrolling |
className | string | "" | Additional CSS classes |
DrawerBody
Prop | Type | Default | Description |
---|---|---|---|
scrollable | boolean | true | Enable body scrolling |
className | string | "" | Additional CSS classes |
Examples
Basic Drawer
A standard bottom drawer with header, body, and footer sections.
Right Position
A drawer that slides in from the right side with rounded corners and padding for a card-like appearance.
Left Position
A drawer that slides in from the left side with full-height coverage, ideal for navigation menus.
Scrollable Content
A drawer with scrollable content for handling large amounts of information.
Styling Approaches
The drawer examples demonstrate two different design patterns:
Full-Height Design (Left Drawer)
- Uses
inset-y-0 left-0 h-full
for complete viewport coverage - No padding or rounded corners for seamless edge-to-edge design
- Ideal for primary navigation, menu systems, and content that requires maximum space
Card-Style Design (Right Drawer)
- Uses
inset-y-4 right-4 h-[calc(100vh-32px)]
withrounded-xl
andshadow-lg
- Includes padding and rounded corners for a floating card appearance
- Perfect for settings panels, user profiles, and secondary content that benefits from visual separation
// Full-height approach (left drawer)
<DrawerContent
position="left"
className="fixed inset-y-0 left-0 h-full border-r"
>
// Card-style approach (right drawer)
<DrawerContent
position="right"
className="fixed inset-y-4 right-4 h-[calc(100vh-32px)] rounded-xl border shadow-lg"
>