Components
Sheet
A panel that slides in from any edge of the screen to hold supplementary content, forms, or navigation without leaving the current page.
Basic usage
Compose a SheetTrigger and SheetContent. The Radix root manages open state for you — no useState required. Only the header and footer are padded, so free-standing content needs its own px-4.
Sides
Set side on SheetContent to choose the edge the panel enters from. Left and right panels span the viewport height at w-3/4, capped at sm:max-w-sm; top and bottom span its width and size to their content.
Header and footer
SheetFooter pins itself to the bottom of the panel — ideal for a primary action paired with a SheetClose dismiss button.
Scrollable content
SheetContent is a flex column, so a middle region with flex-1 overflow-y-auto takes the scroll and leaves the header and the mt-auto footer in place.
Sheet or Drawer?
Sheet is a Radix Dialog: it slides in on a fixed track and closes on Escape or a click on the overlay. Use it for filters, detail panels, and desktop-first side panels — the Tier 3 shell's MobileMenu is a side="left" sheet. When the panel should be dragged — a grab handle, momentum, swipe-to-dismiss on touch — use Drawer, which is built on vaul instead.
Sheet Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state. Pair with onOpenChange. |
defaultOpen | boolean | false | Open state on first render, for uncontrolled usage. |
onOpenChange | (open: boolean) => void | — | Called whenever the sheet opens or closes. |
modal | boolean | true | When true, the rest of the page is inert and hidden from assistive technology while the panel is open. |
childrenrequired | React.ReactNode | — | Sheet trigger and content. |
SheetContent Props
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'right' | 'bottom' | 'left' | 'right' | Edge the panel slides in from. left/right span the full height at w-3/4 (capped at sm:max-w-sm); top/bottom span the full width at h-auto. |
closeLabel | string | 'Đóng' | Visually hidden label on the built-in close button. The package default is Vietnamese — pass an English string in an English UI. |
className | string | — | Merged onto the panel with cn(); the usual place to widen a side panel past sm:max-w-sm. |
…Radix Content | DialogPrimitive.ContentProps | — | Everything else is forwarded to Radix Dialog.Content — onEscapeKeyDown, onInteractOutside, onOpenAutoFocus, forceMount. |
Parts
Every part that renders an element accepts className; on the styled parts it is merged onto the defaults with cn(). Sheet and SheetPortal render no element of their own, so they take no className — passing one is a type error; style SheetContent instead.
| Prop | Type | Default | Description |
|---|---|---|---|
Sheet | DialogPrimitive.Root | — | Stateful container. Holds the open state and the trigger/content pair. |
SheetTrigger | DialogPrimitive.Trigger | — | Element that toggles the sheet. Pass asChild to render your own Button. |
SheetPortal | DialogPrimitive.Portal | — | Portal target. SheetContent renders one already — reach for it only when building a custom panel shell. |
SheetOverlay | DialogPrimitive.Overlay | — | Dimmed backdrop (bg-ink/60, dark:bg-ink/80, backdrop-blur). Also rendered for you by SheetContent. |
SheetContent | DialogPrimitive.Content | — | The sliding panel: portal + overlay + a flex column with gap-4 and a built-in close button. |
SheetHeader | div | — | Top region for title and description. Carries its own p-4 — the panel itself is unpadded. |
SheetTitle | DialogPrimitive.Title | — | Accessible name for the panel. Required for screen-reader announcements. |
SheetDescription | DialogPrimitive.Description | — | Supporting text linked to the panel via aria-describedby. |
SheetFooter | div | — | Bottom region for actions: mt-auto pins it to the base of the panel, p-4 matches the header. |
SheetClose | DialogPrimitive.Close | — | Dismisses the sheet. Use asChild to wrap a custom Button. |
Accessibility
- Built on Radix Dialog: the panel is a modal
role="dialog"with focus trapped inside while open and restored to the trigger on close. - Always include a
SheetTitle— it provides thearia-labelledbyname announced to screen readers;SheetDescriptionwires uparia-describedby. - Pressing Esc or clicking the dimmed overlay closes the sheet. The built-in close button has no visible text — its accessible name is the visually hidden
closeLabel, which defaults to the Vietnamese"Đóng", so passcloseLabel="Close"in English interfaces. - Content outside the open panel is inert and hidden from assistive technology, keeping keyboard navigation scoped to the sheet.