2 Sheet
L4stIdi0t edited this page 2026-09-09 07:00:36 +02:00

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
sheet sheet in dark mode

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.
  • class is 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 is sm:max-w-sm, and below sm every 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


← All components · Getting started · Theming · source