Drawer

A panel that slides in from the left or right edge of the viewport. Distinct from BottomSheet (which slides up on mobile) — Drawer is a desktop-first side panel for settings, filters, or detail views.

Preview

Motion

ElementEnterExit
Backdropopacity 0 → 1 (200ms ease-out)opacity 1 → 0 (200ms ease)
Panel (right)translateX(100%) → 0 (250ms ease)0 → translateX(100%) (250ms ease)
Panel (left)translateX(-100%) → 0 (250ms ease)0 → translateX(-100%) (250ms ease)

Drawer vs Bottom Sheet

DrawerBottom Sheet
Primary axisHorizontal (left/right)Vertical (bottom)
Primary contextDesktop — settings, filters, detail panelsMobile — action sheets, quick options
Content heightFull viewport heightPartial (snap points)
WidthFixed, configurableFull width

Implementation

DrawerUsage.tsx
tsx
"use client";

import { useState } from "react";
import { Drawer } from "@/components/ui/Drawer";
import { Button } from "@/components/ui/Button";

export function Example() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>Open drawer</Button>

      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        title="Settings"
        side="right"
        width={400}
      >
        <p>Drawer content goes here.</p>
      </Drawer>
    </>
  );
}

Props

PropTypeDefaultDescription
open*booleanControls whether the drawer is visible.
onClose*() => voidCalled when the user presses Escape, clicks the backdrop, or presses the close button.
side"left" | "right""right"Which edge the drawer slides in from.
widthstring | number360Width of the drawer panel. Accepts a pixel number or any valid CSS width string.
titleReact.ReactNodeTitle shown in the drawer header. Also used as aria-label when it is a string.
children*React.ReactNodeScrollable body content.

ARIA roles

ElementRoleKey attributes
Paneldialogaria-modal='true', aria-label (from title prop)
Close buttonbutton (implicit)aria-label='Close drawer'
Backdrop(decorative)aria-hidden='true'

Keyboard

KeyAction
EscapeClose the drawer and restore focus to the trigger element
TabCycle forward through focusable elements inside the drawer (focus trapped)
Shift+TabCycle backward through focusable elements inside the drawer (focus trapped)

Accessibility

  • Panel uses role="dialog" and aria-modal="true" — assistive technologies treat it as a modal dialog.
  • Focus moves to the close button on open and returns to the trigger element on close.
  • Escape closes the drawer — consistent with other overlay components (Modal, CommandPalette).
  • Backdrop click also closes the drawer — both dismiss methods are equally supported.
  • The title prop is used as aria-label when it is a string, providing an accessible name for the dialog.