Sheet
A panel that slides in from an edge of the window over a dimmed page, with a header, a scrolling panel and a footer.
ui.sheet
components/ui/sheet.tsxUse case
Use it for work that needs more height than a dialog while keeping the page in sight: the filters of an orders list, a client's full details opened from a table row, a new invoice with many lines. It comes from the right by default (`side` also takes left, top and bottom), and `variant="inset"` floats it a little off the window's edges with rounded corners.
Use it when
- Filters or view settings for the list behind it
- Reading or editing one record opened from a table row
- A form longer than a dialog comfortably holds
- The tool's places on a narrow window (`side="left"`)
Use something else when
- A short task of a few fields: Dialog
- A panel on a phone that follows the finger and closes with a swipe: Drawer
- The tool's main navigation on a wide window: Sidebar
Examples
Code
Import
import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import {
Sheet,
SheetClose,
SheetDescription,
SheetFooter,
SheetHeader,
SheetPanel,
SheetPopup,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"Usage
<Sheet>
<SheetTrigger render={<Button variant="secondary" />}>Filters</SheetTrigger>
<SheetPopup side="right" variant="inset" className="sm:max-w-sm">
<SheetHeader>
<SheetTitle>Filters</SheetTitle>
<SheetDescription>Narrow the list to what you need now.</SheetDescription>
</SheetHeader>
<SheetPanel className="grid gap-1">
{["Unpaid only", "Assigned to me", "Due this week"].map((f) => (
<Label key={f} className="flex h-11 items-center justify-between rounded-[12px] px-3 font-normal hover:bg-surface">
{f}
<Switch />
</Label>
))}
</SheetPanel>
<SheetFooter>
<SheetClose render={<Button variant="ghost" />}>Reset</SheetClose>
<SheetClose render={<Button />}>Show 24 Results</SheetClose>
</SheetFooter>
</SheetPopup>
</Sheet>Rules
- Long content goes in `SheetPanel`, which scrolls between the header and footer and fades at its edges.
- A `<form>` placed directly inside `SheetPopup` wraps the header, panel and footer and is laid out as contents, so the footer stays at the sheet's foot.
- The footer's primary is last and says what it does, with a count when it has one ("Show 24 Results"); the way back (Reset, Cancel) comes before it.
- A left or right sheet is capped at `max-w-md` and leaves part of the page showing; narrow it with `sm:max-w-sm`, never widen it into a page.