Drawer
A panel that slides out from the edge of the screen.
When to Use
Use Drawer when you need to:
- Present secondary content or actions without leaving the current page
- Collect user input in a mobile-friendly sliding panel
- Show contextual forms like profile editing, settings, or filters
- Provide a touch-friendly overlay with swipe-to-dismiss support
- Display confirmation flows or multi-step processes in a compact surface
When Not to Use
- Critical confirmations requiring immediate attention - use Alert Dialog
- Desktop-focused slide-in panels without swipe - use Sheet
- Complex multi-panel layouts - use Sidebar
- Simple informational popups - use Dialog
Default
Basic drawer with form content, sliding up from the bottom edge.
Animation Styles
Choose an animation style that matches your interface personality. Each preset adjusts duration, easing, and physics.
Directions
The drawer can slide in from any edge of the screen. Horizontal drawers constrain width; vertical drawers constrain height.
UX & Design Guidelines
Animation Selection
Use animation="natural" as the default for professional interfaces. animation="snappy" works well for productivity apps where speed matters. animation="rubber-band" and animation="bounce" suit playful or consumer-facing UIs. Reserve animation="gentle" for calm, minimal interfaces where subtlety is preferred.
Content & Layout
Keep drawer content focused on a single task. Use DrawerHeader for title and description, and DrawerFooter for action buttons. Bottom drawers should not exceed 80vh to ensure the user can see the page behind. For forms, place the primary action on the right in the footer.
Responsive Behavior
Drawers are inherently mobile-friendly with built-in swipe-to-dismiss. On mobile, prefer direction="bottom" for natural thumb-reachable placement. Horizontal drawers (left/right) constrain to w-3/4 on mobile and sm:max-w-sm on larger screens.
Color & Contrast
The drawer uses bg-background for the content panel and bg-black/50 for the overlay, providing clear separation from the page. The drag handle uses bg-muted for subtle visibility. All text within the drawer follows the standard text-foreground / text-muted-foreground hierarchy for WCAG 2.1 AA compliance.
Accessibility
Keyboard Navigation
- Tab — Move focus between interactive elements inside the drawer
- Escape — Close the drawer and return focus to the trigger
- Enter or Space — Activate the trigger button to open the drawer
Focus Management
Focus is trapped within the drawer when open, preventing interaction with background content. When the drawer opens, focus moves to the first focusable element inside the drawer content. On close, focus returns to the element that triggered the drawer (the DrawerTrigger).
Screen Reader Support
- Built on Vaul (Radix Dialog primitives), providing full ARIA dialog semantics
DrawerTitleis required and announces the drawer purpose viaaria-labelledbyDrawerDescriptionprovides supplemental context viaaria-describedby- Background content is hidden from assistive technology when the drawer is open
Touch & Gesture Support
Swipe gestures allow dismissing the drawer on touch devices. The drag handle (bottom drawers) provides a clear affordance for swiping. Animations respect the prefers-reduced-motion media query, reducing or disabling motion for users who prefer it.
ARIA Attributes
{/* Standard drawer with descriptive title */}
<Drawer>
<DrawerTrigger asChild>
<Button>Edit Profile</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Edit Profile</DrawerTitle>
<DrawerDescription>
Update your name and preferences.
</DrawerDescription>
</DrawerHeader>
{/* Form content */}
</DrawerContent>
</Drawer>
{/* Drawer with aria-describedby for extra context */}
<Drawer>
<DrawerTrigger asChild>
<Button variant="destructive">Delete Account</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Confirm Deletion</DrawerTitle>
<DrawerDescription id="delete-desc">
This action is permanent and cannot be undone.
</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button variant="destructive" aria-describedby="delete-desc">
Delete permanently
</Button>
<DrawerClose asChild>
<Button variant="outline">Cancel</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>Related Components
API Reference
The Drawer component accepts the following props in addition to standard Vaul drawer attributes.
Drawer (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
| animation | "natural" | "rubber-band" | "snappy" | "spring" | "bounce" | "gentle" | "natural" | Animation style for open/close transitions. |
| direction | "top" | "bottom" | "left" | "right" | "bottom" | The edge from which the drawer slides in. |
| open | boolean | — | Controlled open state of the drawer. |
| onOpenChange | (open: boolean) => void | — | Event handler called when the open state changes. |
| shouldScaleBackground | boolean | false | Whether to scale the background content when the drawer opens. |
| dismissible | boolean | true | Whether the drawer can be dismissed by clicking outside or pressing Escape. |
| modal | boolean | true | When true, interaction with outside elements is disabled and only drawer content is visible to screen readers. |
DrawerContent
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes to apply to the drawer content panel. |
| children | ReactNode | — | Content to render inside the drawer panel. |
DrawerHeader
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the header container. |
DrawerFooter
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the footer container. |