Overlays
Sheet
A panel that slides in from an edge of the screen for editing or inspecting a record without leaving the page.
npx prodular-ui add sheetEdit a record
Header and footer stay fixed, SheetBody scrolls.
import { Button } from "@/components/ui/button"import { Field, FieldDescription, FieldGroup, FieldLabel } from "@/components/ui/field"import { Input } from "@/components/ui/input"import { Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger,} from "@/components/ui/sheet"import { Switch } from "@/components/ui/switch"import { Textarea } from "@/components/ui/textarea"
export default function SheetEdit() { return ( <Sheet> <SheetTrigger render={<Button variant="outline" />}>Edit customer</SheetTrigger> <SheetContent> <SheetHeader> <SheetTitle>Northgate Logistics</SheetTitle> <SheetDescription>Enterprise plan, renews on March 1. Changes sync to the CRM.</SheetDescription> </SheetHeader> <SheetBody> <FieldGroup className="gap-5"> <Field> <FieldLabel>Account name</FieldLabel> <Input defaultValue="Northgate Logistics" /> </Field> <Field> <FieldLabel>Billing email</FieldLabel> <Input type="email" defaultValue="ap@northgate.co" /> <FieldDescription>Invoices and payment receipts go here.</FieldDescription> </Field> <Field> <FieldLabel>Seats</FieldLabel> <Input type="number" defaultValue={240} className="tabular-nums" /> </Field> <Field> <FieldLabel>Internal notes</FieldLabel> <Textarea rows={4} defaultValue="Champion is Dana Reyes (VP Ops). Expansion to the EU warehouses is planned for Q2." /> </Field> <Field orientation="horizontal"> <FieldLabel>Priority support</FieldLabel> <Switch defaultChecked /> </Field> </FieldGroup> </SheetBody> <SheetFooter> <SheetClose render={<Button variant="outline" />}>Cancel</SheetClose> <Button>Save changes</Button> </SheetFooter> </SheetContent> </Sheet> )}Sides
import { Button } from "@/components/ui/button"import { Sheet, SheetBody, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger,} from "@/components/ui/sheet"
const sides = ["top", "right", "bottom", "left"] as const
const activity = [ { who: "Priya Raman", what: "closed REL-482", when: "2m ago" }, { who: "Tom Becker", what: "commented on REL-479", when: "14m ago" }, { who: "Ana Sousa", what: "moved REL-470 to In review", when: "1h ago" },]
export default function SheetSides() { return ( <div className="flex flex-wrap items-center justify-center gap-3"> {sides.map((side) => ( <Sheet key={side}> <SheetTrigger render={<Button variant="outline" className="capitalize" />}>{side}</SheetTrigger> <SheetContent side={side}> <SheetHeader> <SheetTitle>Team activity</SheetTitle> <SheetDescription>The last hour in the Platform team.</SheetDescription> </SheetHeader> <SheetBody className="gap-0 divide-y py-0"> {activity.map((a) => ( <div key={a.what} className="flex items-baseline justify-between gap-4 py-3 text-sm"> <span> <span className="font-medium">{a.who}</span>{" "} <span className="text-muted-foreground">{a.what}</span> </span> <span className="shrink-0 text-xs text-muted-foreground tabular-nums">{a.when}</span> </div> ))} </SheetBody> </SheetContent> </Sheet> ))} </div> )}Floating
variant floating insets the sheet from the edges with rounded corners. Good for detail peeks.
import { Button } from "@/components/ui/button"import { Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger,} from "@/components/ui/sheet"
const fields = [ ["Status", "In review"], ["Assignee", "Ana Sousa"], ["Priority", "High"], ["Cycle", "Cycle 31, ends Oct 28"], ["Estimate", "3 points"],]
export default function SheetFloating() { return ( <Sheet> <SheetTrigger render={<Button variant="outline" />}>Open REL-470</SheetTrigger> <SheetContent variant="floating" className="sm:max-w-sm"> <SheetHeader> <SheetTitle>Retry failed webhook deliveries</SheetTitle> <SheetDescription>REL-470 in Platform</SheetDescription> </SheetHeader> <SheetBody> <dl className="grid grid-cols-[7rem_1fr] gap-x-4 gap-y-3 text-sm"> {fields.map(([k, v]) => ( <div key={k} className="contents"> <dt className="text-muted-foreground">{k}</dt> <dd className="font-medium">{v}</dd> </div> ))} </dl> <p className="border-t pt-5 text-sm text-muted-foreground"> Deliveries that fail with a 5xx are retried with backoff for 24 hours, then marked as dead and surfaced in the developer dashboard. </p> </SheetBody> <SheetFooter> <SheetClose render={<Button variant="outline" />}>Close</SheetClose> <Button>Open issue</Button> </SheetFooter> </SheetContent> </Sheet> )}Anatomy
<Sheet> <SheetTrigger render={<Button variant="outline" />}>Edit customer</SheetTrigger> <SheetContent side="right"> <SheetHeader> <SheetTitle>Northgate Logistics</SheetTitle> <SheetDescription>Changes sync to the CRM.</SheetDescription> </SheetHeader> <SheetBody>{/* fields */}</SheetBody> <SheetFooter> <SheetClose render={<Button variant="outline" />}>Cancel</SheetClose> <Button>Save changes</Button> </SheetFooter> </SheetContent></Sheet>Guidance
Use it when
- Use right side sheets to edit or inspect one record from a list, so the list stays in context.
- Use bottom sheets on small screens for short pickers. Consider Drawer when swipe to dismiss matters.
- Use the floating variant for quick, read mostly peeks.
Avoid
- Short confirmations. Use Alert dialog.
- Very wide content such as tables with many columns. Use a page.
- Stacking a sheet on top of a dialog.
Rules for AI agents
Published in llms-full.txt and the registry, so coding agents follow them when they build with this component.
- Always render SheetTitle inside SheetHeader. Use className="sr-only" if it must be hidden.
- Compose as SheetHeader, SheetBody, SheetFooter. Only SheetBody scrolls.
- Use side="right" by default. Use left only for navigation.
- Put Cancel as SheetClose render={<Button variant="outline" />} before the primary action in SheetFooter.
- Override width with a max-w class on SheetContent (for example sm:max-w-lg), never with a pixel width.
API
SheetContent
| Prop | Type | Default | Description |
|---|---|---|---|
| side | "top" | "right" | "bottom" | "left" | "right" | Edge the sheet slides in from. |
| variant | "default" | "floating" | "default" | floating adds a margin, a full border and rounded corners. |
| showCloseButton | boolean | true | Renders the icon close button. |