Skip to content

Overlays & navigation

Sheet

A sheet is a dialog that slides in from the edge of the screen. Use it to edit a record without leaving the list, for filters, or for side panels such as activity and settings. It shares Dialog's native <dialog> foundation, so focus, Escape and the backdrop behave the same; the header and footer stay put while the body scrolls.

On this page

Edit customer

Changes apply to new invoices for Fernhill Studio.

3 days before and 7 days after the due date.

Usage

components/ui/sheet.tsx
import { Sheet, SheetBody, SheetFooter, SheetHeader } from "@/components/ui/sheet"; <Sheet open={open} onClose={() => setOpen(false)}>  <SheetHeader title="Edit customer" description="Changes apply to new invoices." />  <SheetBody>…</SheetBody>  <SheetFooter>    <Button variant="primary" onClick={save}>Save changes</Button>  </SheetFooter></Sheet>

Examples

Edit a record

A right-side sheet with a form. The body scrolls on short screens; the header and the Save button never leave the view.

Edit customer

Changes apply to new invoices for Fernhill Studio.

3 days before and 7 days after the due date.

Sides

Right is the default. Left suits navigation; bottom gets a grab handle and rounded top corners, and works well for filters on phones.

Filter invoices

Show invoices that match any of these.

Side panel with actions

`actions` puts extra controls in the header, before the close button. A long list scrolls inside the body.

Activity

4 unread

  • Ada Moreno paid invoice INV-20412 min ago

    Unread
  • Jonas Whitfield commented on Q3 retainer18 min ago

    Unread
  • Priya Raman approved the Fernhill estimate1 h ago

    Unread
  • Leo Achterberg added 3 expenses3 h ago

    Unread
  • Mina Okafor invited you to Quarry & CoYesterday

  • Ada Moreno downloaded the March statementYesterday

  • Tomás Vidal marked INV-2033 as disputedMon

  • Priya Raman changed payment terms to Net 30Mon

  • Jonas Whitfield created a recurring invoiceLast week

  • Leo Achterberg connected a bank accountLast week

Props

Sheet

  • openrequiredbooleandefault: —Whether the sheet is shown.
  • onCloserequired() => voiddefault: —Called for Escape, a backdrop click, the × button and DialogClose.
  • side"right" | "left" | "bottom"default: "right"Edge the sheet slides in from.
  • size"sm" | "md" | "lg"default: "md"Width of left and right sheets from 640px up: 384, 448 or 576px. Phones get the full width minus 40px.
  • aria-labelstringdefault: —Name for sheets without a SheetHeader.

SheetHeader

  • titlerequiredReactNodedefault: —Heading and accessible name of the sheet.
  • descriptionReactNodedefault: —Supporting line, linked with aria-describedby.
  • actionsReactNodedefault: —Extra buttons placed before the close button.
  • hideClosebooleandefault: falseHide the × button.

SheetBody, SheetFooter

  • SheetBody{ className, children }default: —Scrolling content with 20px padding. Pass p-0 for edge-to-edge lists.
  • SheetFooter{ className, children }default: —Pinned actions, right-aligned. Respects the iPhone home indicator.

Accessibility

  • A sheet is a modal <dialog>: the page behind is inert, Tab cycles inside the sheet and focus returns to the trigger on close.
  • Escape and a click on the backdrop close the sheet. The × button is labelled “Close”.
  • SheetHeader's title names the sheet and its description is announced with it.
  • The slide animation is turned off when the reader prefers reduced motion.

Suggested