Sheet · Drawer
Sheet — a panel that slides in from the side and keeps the page behind it: a table’s filters, a row’s detail, a form too long for a Popover.
Beta · Navigation and overlay · packages/css/src/components/sheet.css
.pui-sheet (--left; the Dialog’s header parts, __content __footer) · .pui-drawer (__handle, stacked full-width buttons in __footer). Both over .pui-scrim.
Sizes across, states down.
Sheet — Beta
Section titled “Sheet — Beta”- Title, Description + Has description; Content (swap — default Slot; a consumer points it at its own component: Fields, a Checkbox list, a Table); Has footer + the exposed Actions; the Close exposed
- Side: right (the default) · left (a navigation sheet on a narrow screen); 384 × the viewport’s height — the specimen is 640
- No states: open or not; the Scrim behind, the page’s scroll locked
Use when a task belongs beside the page and returns to it — filters on a Data table, a row’s detail with its fields, a settings group longer than a Popover holds.
Do not use when the page must stop (Dialog); the content is a few controls (Popover); on a phone from the side (Drawer, from the bottom); as a second sidebar that stays (a docked panel, later).
Relates to Dialog, Drawer, Popover, Scrim, Slot, Button group, Data table, Tabs.
Anti-patterns a sheet wider than 384 on the web (that is a page) · a sheet without a close · two sheets · a footer with two primary verbs · the Slot left showing · a fill changed on the instance.
Keywords: sheet, side panel, offcanvas, filters, row detail, slide-over
Figma — page Sheet & Drawer: Sheet (2 variants)
shadcn: sheet
Drawer — Beta
Section titled “Drawer — Beta”Drawer — the bottom sheet on a phone: slides up from the bottom edge, a handle to drag it down, the page dimmed behind.
- Title, Description + Has description; Content (swap — default Slot); Has footer (Primary and Secondary exposed); Has close (off — on when a drawer holds a form that must not be swiped away)
- The height follows the content; never taller than the screen minus 48
Use when on a phone, a choice or a short form that belongs to the screen — move to a folder, share, a filter, confirm with context.
Do not use when on the web (Sheet or Dialog); the content scrolls for more than a screen (a page); a yes / no question (Alert dialog).
Relates to Sheet, Dialog, Alert dialog, Scrim, Slot, Button.
Anti-patterns a drawer without its handle · a drawer from the side (that is Sheet) · a footer beside the content instead of stacked · a fill changed on the instance.
Keywords: drawer, bottom sheet, mobile, vaul, slide-up
Figma — page Sheet & Drawer: Drawer (1 variants)
shadcn: drawer
The markup — copy this
Section titled “The markup — copy this”The class, the parts, and nothing that is not in the package. The same block opens sheet.css.
<div class="pui-scrim"><div class="pui-sheet" role="dialog" aria-modal="true" aria-labelledby="t"> …__header (h2#t), __content, __footer… </div></div><div class="pui-scrim"><div class="pui-drawer" role="dialog" aria-labelledby="t"><div class="pui-drawer__handle"></div> …__header, __content, __footer… </div></div>The modifiers
Section titled “The modifiers”| What it is | Note | |
|---|---|---|
| Sheet side | (none) right · --left | — |
Accessibility — measured, not assumed
Section titled “Accessibility — measured, not assumed”Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.
Contrast
Section titled “Contrast”| ink on ground | reads | floor | the matrix calls it | |
|---|---|---|---|---|
#544d4d on #ffffff |
8.24 | 4.5 | text.muted on surface.page (promised) | ok |
#0b0202 on #e9e9fb |
17.1 | 4.5 | KPI value, blue tile (promised) | ok |
#0b0202 on #ffffff |
20.51 | 4.5 | text.default on surface.page (promised) | ok |
#ffffff on #0b0202 |
20.51 | 4.5 | Primary button label (promised) | ok |
4 distinct pair(s) rendered, 0 that axe calls a violation.
The focus ring
Section titled “The focus ring”7 of 7 focus stop(s) in this block meet WCAG 2.4.13 on screen — the same crop screenshotted focused and unfocused, and the difference measured.
Keyboard
Section titled “Keyboard”| role | tab stops | what the pattern requires | |
|---|---|---|---|
dialog .pui-sheet |
5 | — | — |
dialog .pui-drawer |
2 | — | — |
What the consumer’s script owes. as Dialog: focus in on open, held while open, Escape closes and returns it to the opener.
Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).
Pepper UI v1.5.0
The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.