Skip to content
Component

Drawer

Slides in from left, right, top, or bottom via the `side` prop.

All sides

  • Use side="bottom" as a mobile-first sheet preset: same component, no separate Sheet needed

When to use

  • Secondary navigation or filters the user may want to keep referencing (site nav on mobile, a filters panel).
  • A cart, notification list, or detail panel that should slide in alongside the page rather than fully block it.
  • side="bottom" as a mobile-first "sheet" - actions, quick forms, or a picker triggered from a bottom bar.

When not to use

  • A task the user must complete or explicitly dismiss before continuing - use Dialog (or Dialog with mobileBehavior="sheet", which is the desktop-dialog/mobile-sheet combination Drawer doesn't do on its own).
  • Short, anchored content next to a trigger - use Popover instead of a full-height panel.

Keyboard

KeyAction
EscapeCloses the drawer and returns focus to the trigger.
Tab / Shift+TabCycles focus within the drawer only - focus is trapped while open.

Mobile behavior

  • side="left" / "right": full-height panel, width caps at calc(100vw - 3rem) so the page edge stays visible.
  • side="top" / "bottom": full-width panel, height caps at 85vh; side="bottom" is the standard mobile action-sheet pattern.
  • Respects env(safe-area-inset-bottom) on the bottom side so content clears the home indicator on notched devices.

Accessibility notes

  • Uses Base UI's Drawer primitive: role="dialog", focus trap, and scroll lock on the page behind it.
  • Drawer.Title is required for an accessible name - pass a visually-hidden one if the panel doesn't need a visible heading.

Common mistakes

  • Putting primary page navigation only in a Drawer on desktop - reserve Drawer navigation for mobile; use a persistent Sidebar on larger screens.
  • Skipping Drawer.Title - the panel then announces with no accessible name.
  • Stacking more than one Drawer open at once - close the first before opening a second, or use Popover for the secondary surface.

Known limitations

  • No built-in resizable/draggable width - the panel width is fixed by the `w-80` / viewport-cap classes in the recipe.

Related components

Drawer.Content props

side"right"
"left" | "right" | "top" | "bottom"

Which edge the panel slides in from.

hideCloseButtonfalse
boolean

Hides the built-in close button.

classNameNone
string

Extra classes merged onto the panel surface.

CriterionStatusNote
Keyboard supportSupportedEscape closes; Tab/Shift+Tab cycle within a focus trap.
Focus managementSupportedFocus enters the panel on open, returns to the trigger on close.
Screen reader labelsPartialDrawer.Title gives an accessible name; omitting it leaves the panel unlabeled.
Reduced motionSupportedprefers-reduced-motion: reduce zeroes all Fuji transition durations globally.
Reduced transparencySupportedprefers-reduced-transparency: reduce flattens Glass to opaque surfaces (portals included).
RTL layoutPartialLogical flex/grid gap works under dir="rtl"; directional chevrons are not yet mirrored.

API reference

open / defaultOpenNone
boolean

Controlled or initial drawer state.

side"right"
left | right | top | bottom

Entering edge.

hideCloseButtonfalse
boolean

Hides the bare X dismiss control.

classNameNone
string

Additional classes applied to the component root.