Skip to content
Design System
Contact

Drawer

Side sheets for record detail and a draggable bottom drawer for mobile.

ComponentsRadix Dialog (Sheet)vaul

Playground

The wireframe shows where the sheet docks and how wide it gets; the button opens the real one. Sheets slide in from an edge and keep the page visible behind a light overlay.

Preview

Props

Side
Width
example.tsxtsx
1import { Button } from "@/components/ui/button"
2import {
3 Sheet,
4 SheetClose,
5 SheetContent,
6 SheetDescription,
7 SheetFooter,
8 SheetHeader,
9 SheetTitle,
10 SheetTrigger,
11} from "@/components/ui/sheet"
12
13<Sheet>
14 <SheetTrigger asChild>
15 <Button variant="outline">Open filters</Button>
16 </SheetTrigger>
17 <SheetContent>
18 <SheetHeader>
19 <SheetTitle>Filters</SheetTitle>
20 <SheetDescription>Narrow the deals list by stage.</SheetDescription>
21 </SheetHeader>
22 <fieldset className="grid gap-2.5 px-4">{/* checkboxes */}</fieldset>
23 <SheetFooter className="flex-row justify-end border-t">
24 <Button variant="ghost">Clear</Button>
25 <SheetClose asChild>
26 <Button>Apply filters</Button>
27 </SheetClose>
28 </SheetFooter>
29 </SheetContent>
30</Sheet>

Sheet, drawer or modal

All three trap focus and dim the page. Pick by how much context people need and how they hold the device.

Sheet

Radix Dialog, docked to an edge

Use for
Record detail, filters and edit forms where the list behind stays useful for context.
Avoid for
Short confirmations. The panel is too heavy for a yes or no.

Drawer

vaul, draggable with snap points

Use for
Touch-first action lists and pickers on phones, where a thumb can reach the bottom edge.
Avoid for
Desktop layouts. A menu or a sheet fits pointer input better.

Modal

Radix Dialog, centered

Use for
Blocking decisions and short focused tasks that must be finished or cancelled first.
Avoid for
Long forms or anything people need to compare with the page behind.

States

States of the trigger. Once open, the panel follows the Modal states: submitting locks the footer, errors stay inline.

States
  • Defaultrest
  • Hover:hover
  • Focus:focus-visible
  • Loadingaria-busy
  • Disableddisabled
  • Erroraria-invalid
  • Successdata-state=success

Examples

A record-detail sheet opened from a list, with properties, tabs and footer actions, and a vaul drawer for touch with a peek and a full snap point.

Record detail sheet
Demo data
Mobile actions drawer
Demo data
Deals
G

Globex

Enterprise rollout

$125,000Proposal

Opens at a 45% peek. Drag up, or use the chevron, to snap to full height.

API

Sheet wraps Radix Dialog; Drawer wraps vaul, which is also built on Radix Dialog.

PropTypeDefaultDescription
SheetContent side"top" | "right" | "bottom" | "left""right"Edge the panel slides from. Right for record detail, left for navigation.
SheetContent classNamestring—Widen with the same variant as the base: data-[side=right]:sm:max-w-md. Phones get 75% width.
showCloseButtonbooleantrueThe X in the top-right corner.
onInteractOutside(event: Event) => void—preventDefault() keeps the sheet open on overlay clicks, e.g. with unsaved edits.
Drawer snapPoints(number | string)[]—Fractions of the viewport or px strings, smallest first, e.g. [0.45, 1].
Drawer activeSnapPointnumber | string | null—Controlled snap point, with setActiveSnapPoint.
Drawer direction"bottom" | "top" | "left" | "right""bottom"Edge the drawer is dragged from.
Drawer dismissiblebooleantrueWhen false, dragging down or clicking outside does not close it.

Accessibility

Keyboard

Move within the panel, focus is trapped
Tab
Close and return focus to the trigger
Esc
Open from the row or button
EnterorSpace

Semantics and ARIA

  • Both render a dialog with aria-modal, named by the title and described by the description. The page behind is hidden from assistive tech.
  • Rows that open a sheet are real buttons with aria-haspopup="dialog", so focus returns to the exact row on close.
  • Dragging is never the only way: the drawer has a Done button and an expand button with an aria-label, and Esc closes it.
  • Actions in the drawer are at least 44px tall for touch. Destructive ones are last and confirmed before they run.
  • Blocking overlay dismissal is for unsaved work only. Esc and the close button still work, so nobody gets stuck.