Overlays/Drawer

Drawer

A panel that slides out from the edge of the screen.

Themed

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
  • DrawerTitle is required and announces the drawer purpose via aria-labelledby
  • DrawerDescription provides supplemental context via aria-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>

API Reference

The Drawer component accepts the following props in addition to standard Vaul drawer attributes.

Drawer (Root)

PropTypeDefaultDescription
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.
openbooleanControlled open state of the drawer.
onOpenChange(open: boolean) => voidEvent handler called when the open state changes.
shouldScaleBackgroundbooleanfalseWhether to scale the background content when the drawer opens.
dismissiblebooleantrueWhether the drawer can be dismissed by clicking outside or pressing Escape.
modalbooleantrueWhen true, interaction with outside elements is disabled and only drawer content is visible to screen readers.

DrawerContent

PropTypeDefaultDescription
classNamestringAdditional CSS classes to apply to the drawer content panel.
childrenReactNodeContent to render inside the drawer panel.

DrawerHeader

PropTypeDefaultDescription
classNamestringAdditional CSS classes for the header container.

DrawerFooter

PropTypeDefaultDescription
classNamestringAdditional CSS classes for the footer container.