Sheet
Bottom sheet on a native <dialog> (Material BottomSheet equivalent): a bottom-anchored glass surface — full-width to 640px, centered, top corners rounded, max-height 60vh (90vh with .sheet-tall) — sliding up over a blanket backdrop. Use for mobile-friendly action lists, share targets, and quick forms. Open declaratively with <button commandfor="id" command="show-modal"> and close with command="close" or a <form method="dialog">; no JavaScript involved.
Root: .sheet on <dialog>
Examples
<dialog class="sheet" id="share-sheet" aria-labelledby="share-sheet-title"><div class="sheet-handle"></div><div class="sheet-header"><h4 class="sheet-title" id="share-sheet-title">Share board</h4></div><div class="sheet-body"><p>Choose a destination…</p></div><form method="dialog" class="sheet-footer"><button class="btn btn-subtle" value="cancel">Cancel</button></form></dialog>
<dialog class="sheet sheet-tall" id="filter-sheet" aria-label="Filters"><div class="sheet-handle"></div><div class="sheet-body"><p>Filter controls…</p></div></dialog>
Contract
Variants & modifiers
| Class | Axis | Rules |
|---|---|---|
sheet-tall | modifier | optional |
Structure
| Selector | Required | Description |
|---|---|---|
.sheet-handle | optional | 32×4 rounded pill (var(--lz-sys-track)) centered at the top — the grab affordance. Purely decorative; keep it an empty div. |
.sheet-header | optional | Title strip below the handle: .sheet-title (h600 scale), space-between for an optional trailing control. |
.sheet-body | required | The scrolling content region (flex:1, overflow-y:auto, 24px inline padding). |
.sheet-footer | optional | End-aligned action row, usually a <form method="dialog"> so buttons close the sheet natively. |
Accessibility
| On | Attribute | Level | When |
|---|---|---|---|
.sheet | aria-labelledby | required | The sheet has a visible .sheet-title — point aria-labelledby at its id; otherwise label the dialog directly with aria-label. |
The native <dialog> supplies focus trapping, Esc-to-close, and top-layer stacking — never re-implement them. Give the dialog an accessible name (aria-labelledby → .sheet-title id, or aria-label). The sheet is a glass surface: never nest another glass surface (modal, drawer, flag, another sheet) inside it. The .sheet-handle is decorative only — there is no built-in drag-to-dismiss; Esc, backdrop behavior, and explicit close buttons do that work. Entrance slide uses motion tokens and is collapsed by the framework-wide prefers-reduced-motion rule.
Nesting
Allowed in:
directly under <body> (the dialog renders in the top layer regardless of DOM position)
Never inside (or containing):
.sheetdialog.modal.drawer.flag
Subcomponents
Modal-fullscreen
Fullscreen dialog (Material fullscreen-dialog equivalent) for mobile-scale creation/edit flows: an edge-to-edge native <dialog> on a solid surface (deliberately NOT glass — nothing behind it remains visible, so translucency would only cost contrast). Reuses the .modal-header idiom with the order close-button → title → confirming action; the title fills the middle.
Root: .modal-fullscreen on <dialog>
Example
<dialog class="modal-fullscreen" id="new-issue" aria-labelledby="new-issue-title"><div class="modal-header"><button class="btn btn-subtle btn-icon" commandfor="new-issue" command="close" aria-label="Close dialog">×</button><h4 class="modal-title" id="new-issue-title">New issue</h4><button class="btn btn-primary" commandfor="new-issue" command="close">Create</button></div><div class="modal-body"><p>Form fields…</p></div></dialog>
Structure
| Selector | Required | Description |
|---|---|---|
.modal-header | required | Top bar, in order: leading close button (.btn .btn-subtle .btn-icon with commandfor + command="close"), .modal-title (flex:1, truncates), then the confirming action (.btn .btn-primary). |
.modal-header > .modal-title | required | Dialog title; give it an id and point the dialog's aria-labelledby at it. |
.modal-body | required | The scrolling content region (flex:1, overflow-y:auto). |
Accessibility
| On | Attribute | Level | When |
|---|---|---|---|
.modal-fullscreen | aria-labelledby | required | Point aria-labelledby at the .modal-title id; use aria-label only if there is no visible title. |
Do not combine with the .modal class — .modal applies the glass material and centered geometry that .modal-fullscreen replaces. The close button is icon-only and must carry aria-label (enforced by the button contract on .btn-icon). Because the dialog covers the viewport, a .snackbar-fixed placed inside it positions against the viewport from the top layer, which is the supported way to toast over a fullscreen flow.
Nesting
Allowed in:
directly under <body> (the dialog renders in the top layer regardless of DOM position)
Never inside (or containing):
.sheetdialog.modal.drawer.flag