Sheet
Sheet is an adaptive overlay with one API and one content: a side panel on wide screens, a draggable bottom sheet on phones.
Import
Install from npm, copy the source into your project with @yugen-ui/cli or the shadcn CLI, or import directly when working in this repo.
// npm install yugen-uiimport { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, SheetFooter, SheetClose,} from "yugen-ui";Variants
Each tile is a standalone example: hover to copy, or press Code to see the source.
Bottom sheet & snap point
mode="bottom" forces the bottom sheet (you can try it with a mouse on desktop). snapPoints [0.45, 0.9]; content only scrolls at the 90% snap point.
Non-modal
modal={false}: no backdrop and no focus trap, so the page behind stays usable. One snap point at 30%; swipe down to close.
Start panel, choice required
side="start" size="medium" on desktop; dismissible={false} blocks Esc, backdrop clicks and swiping down, so people have to pick an action.
Usage
- Always include a SheetTitle; add a SheetDescription when the title doesn't give enough context.
- Put the primary action in SheetFooter. On phones it stays within thumb reach, even at a low snap point.
- Make the lowest snap point just big enough for the common task (a quick look) and use a higher one for details; 2–3 snap points at most.
- Don't use Sheet for short confirmations or destructive actions. Use Dialog modalType="alert".
- Don't put horizontal drag areas (sliders, maps) in the header. The header and the handle drag the sheet.
- Don't open a Sheet on top of a Sheet. Use dismissible={false} only when a choice is truly required.
Props
| Prop · Type | Default | Description |
|---|---|---|
| open / defaultOpen / onOpenChangeboolean / boolean / (open) => void | Default: — | Open state (controlled or uncontrolled). |
| mode"auto" | "side" | "bottom" | Default: "auto" | auto: panel when the viewport is ≥ breakpoint, bottom sheet when it is narrower. |
| breakpoint"lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | number | Default: "3xl" | Minimum viewport width for the panel form, with the same tokens as AppShell: lg 32rem · xl 36rem · 2xl 42rem · 3xl 48rem · 4xl 56rem · 5xl 64rem. A px number is deprecated (removed in 1.0). |
| side"start" | "end" | Default: "end" | Edge the panel slides in from; flipped in RTL. |
| size"small" | "medium" | "large" | Default: "small" | Panel width: 320 / 592 / 940px. |
| snapPointsnumber[] | Default: [0.5, 0.9] | Bottom sheet heights (fractions of the viewport height, 0–1). |
| snapPoint / defaultSnapPoint / onSnapPointChangenumber / number / (snap) => void | Default: — | Current snap point; defaults to the lowest. When uncontrolled, it starts again from defaultSnapPoint each time the sheet opens. |
| modalboolean | Default: true | false: no backdrop, no focus trap or scroll lock, and no closing on an outside click. |
| dismissibleboolean | Default: true | false: blocks closing with Esc, a backdrop click or swiping down. |
| SheetContent | Default: true / "Change height" | Bottom sheet handle; it is a button (Enter, ↑ / ↓) when there are 2 or more snap points. |
| SheetContent | Default: — | Yugen Labs — a glass surface. A glass bottom sheet is inset from the screen edges, rounded on all four corners, and turns opaque at the highest snap point. |
| SheetHeader | Default: — | Element at the end of the header row, usually a close button. |
| data-sheet-no-dragattribute | Default: — | Add it to a child element so touches on it don't drag the sheet. |
Messages
Text built into the component: labels, aria-labels, screen reader announcements.
English by default. Change it with the messages prop of YugenProvider, by the namespace below; messagesVi has the Vietnamese set. See Interface language.
messages.sheet
| Key · Type | Default (English) | messagesVi |
|---|---|---|
| handlestring Nhãn tay nắm đổi nấc chiều cao của bottom sheet (phần "(50%)" được thêm sau). | Default (English)"Change height" | messagesVi"Đổi chiều cao" |