Sheet
A panel that slides in from the edge of the screen, anchored to one side. Built on base-ui Dialog — it is a modal dialog styled as a side drawer, so it inherits focus trapping, scroll locking, the backdrop, and Esc-to-close for free.
Compose the same parts as a Dialog: Sheet (root, owns open state), SheetTrigger (opens it), SheetContent (the drawer surface, takes side and size), and the layout helpers SheetHeader, SheetTitle, SheetDescription, SheetFooter, and SheetClose.
Reach for a Sheet over a Dialog when the content is long, scrollable, or secondary to the page behind it — order detail, an activity log, or a filter panel that the user scans against the list still visible at the edge. Keep a centered Dialog for short, focused decisions (confirm, a small form).
Default
Sheet is uncontrolled — SheetTrigger toggles it. SheetContent defaults to side="right". Put the title and summary in a SheetHeader, the scrollable body in a flex-1 overflow-y-auto region, and the actions in a SheetFooter (which pins itself to the bottom via mt-auto).
Sides
side anchors the drawer to one edge: "right" (default), "left", "top", or "bottom". Left/right sheets fill the viewport height; top/bottom sheets fill its width and auto-size their height to the content.
Size
size sets the drawer width on sm+ screens — sm (default) through 4xl, plus full. It only applies to side="left" and side="right"; top and bottom sheets ignore it and size to their content. Widen the sheet for forms and multi-column detail, like this filter panel.
Controlled
Sheet is uncontrolled by default. To drive it yourself — open it from a row action, or close it after a mutation resolves — pass open and onOpenChange.
const [open, setOpen] = useState(false);
<Sheet open={open} onOpenChange={setOpen}>
<SheetContent>
{/* … */}
<SheetFooter>
<Button onClick={() => setOpen(false)}>Done</Button>
</SheetFooter>
</SheetContent>
</Sheet>;Reference
Sheet
Root container. Extends base-ui Dialog.Root props.
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | false | Initial open state (uncontrolled) |
open | boolean | — | Open state (controlled) |
onOpenChange | (open: boolean) => void | — | Fires when the open state changes |
modal | boolean | true | Trap focus and block the page behind it |
SheetTrigger
Opens the sheet. Extends base-ui Dialog.Trigger props. Pass render to use a Button (or any element) as the trigger.
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | — | Element to render as the trigger |
SheetContent
The drawer surface. Extends base-ui Dialog.Popup props. Renders its own portal, backdrop, and close button.
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" | Edge the sheet is anchored to and slides in from |
size | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "full" | "sm" | Width on sm+ screens; applies to left/right sides only |
showCloseButton | boolean | true | Render the floating close button in the top-right corner |
className | string | — | Merged onto the popup |
SheetHeader
A flex flex-col container with padding for the title and description. Extends div props.
SheetTitle
The accessible title. Extends base-ui Dialog.Title props.
SheetDescription
Supporting text under the title, wired as the dialog’s accessible description. Extends base-ui Dialog.Description props.
SheetFooter
A flex flex-col container pinned to the bottom via mt-auto, for actions. Extends div props.
SheetClose
Closes the sheet. Extends base-ui Dialog.Close props. Pass render to use a Button as the close action.
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | — | Element to render as the close control |