Sheet
A modal panel anchored to an edge of the viewport, for the work that is too wide for a Dialog and too tied to the page to be a route: filters, a detail pane, a settings drawer.
It is a Dialog in every way that matters — role="dialog" aria-modal, focus moved in and trapped, the rest of the page inert, Escape and a backdrop click to close, body scroll locked, portalled to <body> so an ancestor's transform cannot capture it — and differs only in where it sits and which way it slides in. side picks the edge. A left or right sheet is full height and takes its width from class; a top or bottom one is full width and takes its height. It fills the viewport below sm either way, because a panel beside nothing is just a small screen with wasted edges. The header and footer stay put and the body between them scrolls, so a long form keeps its title and its buttons in sight. It slides back out the way it came in. A panel that animates open and then disappears in one frame reads as a bug rather than as speed.
Overlays · two-way: bind:open · portalled to <body> · keyboard contract
<script lang="ts">
import { Sheet } from '@l4st/driftwood';
</script>
| Light | Dark |
|---|---|
![]() |
![]() |
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
open bind: |
boolean |
false |
Opening moves focus in and makes the rest of the page inert. |
side |
'left' | 'right' | 'top' | 'bottom' |
'right' |
Which edge it is anchored to, and slides in from. |
title |
string |
— | Names the sheet for assistive tech (aria-labelledby). |
description |
string |
— | One line under the title; also its aria-describedby. |
class |
string |
— | Sizes the panel: a width for a left/right sheet, a height for a top/bottom one. |
closeLabel |
string |
'Close' |
Accessible name of the close button. |
children required |
Snippet |
— | The content. |
footer |
Snippet |
— | Actions, end-aligned along the bottom. Put the confirming button last. |
Keyboard
| Key | Does |
|---|---|
| Tab / Shift+Tab | cycle within the sheet — focus is trapped |
| Escape | close and return focus to the opener |
Notes
Notes
- Reach for it when a Dialog would be cramped. A Dialog is a question with a couple of buttons; a Sheet is a piece of work — a filter panel, a record's detail, a settings form — that wants the height of the screen and does not want to become a route. Everything a Dialog promises about focus, inerting and Escape is promised here too, because it is the same implementation.
classis the size. A left or right sheet is already full height, so give it a width (class="sm:max-w-2xl"); a top or bottom one is already full width, so give it a height. The default issm:max-w-sm, and belowsmevery side fills the screen.- The body is the only part that scrolls. The title and the footer stay where they are, so the buttons of a long form never scroll out of reach.
| Left | Bottom |
|---|---|
side="left" — navigation, a filter panel |
side="bottom" — a picker, an action list |
- A Drawer is the one with snap points. If what you want is a panel a phone reader drags between a peek and a full height, that is Drawer; a Sheet is one height, chosen by you.
Overlays · Dialog · Drawer · Tooltip · Popover
driftwood
Layout
Actions
Forms
- Field
- Input
- FileInput
- FileList
- Textarea
- CodeEditor
- Combobox
- RadioGroup
- NumberInput
- InlineEdit
- Label
- Select
- MultiSelect
- DatePicker
- TagsInput
- Checkbox
- Switch
- Slider
Feedback
Charts
Overlays
Navigation
Generated from the source by pnpm wiki · repository · v0.24.0

