Trang này chưa có bản tiếng Việt. Nội dung dưới đây là bản tiếng Anh.

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

PropKiểuMặc địnhMô tả
openboolean—Controlled open state. Pair with onOpenChange.
defaultOpenbooleanfalseOpen state on first render, for uncontrolled usage.
onOpenChange(open: boolean) => void—Called whenever the sheet opens or closes.
modalbooleantrueWhen true, the rest of the page is inert and hidden from assistive technology while the panel is open.
childrenbắt buộcReact.ReactNode—Sheet trigger and content.

SheetContent Props

PropKiểuMặc địnhMô tả
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.
closeLabelstring'Close'Visually hidden label on the built-in close button. Follows ComitorLocaleProvider — “Đóng” under locale="vi" — and a value passed here wins, e.g. 'Close filters' when the panel should be named.
classNamestring—Merged onto the panel with cn(); the usual place to widen a side panel past sm:max-w-sm.
onCloseAutoFocus(event: Event) => void—Runs as the sheet closes, before focus moves — ahead of both Radix and the package's own focus return, so it wins: call event.preventDefault() and focus what should come next. Keep one that sends focus somewhere else; one that only re-focused the opener can go, since SheetContent does that itself (see Accessibility).
…Radix ContentDialogPrimitive.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.

PropKiểuMặc địnhMô tả
SheetDialogPrimitive.Root—Stateful container. Holds the open state and the trigger/content pair.
SheetTriggerDialogPrimitive.Trigger—Element that toggles the sheet. Pass asChild to render your own Button.
SheetPortalDialogPrimitive.Portal—Portal target. SheetContent renders one already — reach for it only when building a custom panel shell.
SheetOverlayDialogPrimitive.Overlay—Dimmed backdrop (bg-ink/60, dark:bg-ink/80, backdrop-blur). Also rendered for you by SheetContent.
SheetContentDialogPrimitive.Content—The sliding panel: portal + overlay + a flex column with gap-4 and a built-in close button.
SheetHeaderdiv—Top region for title and description. Carries its own p-4 — the panel itself is unpadded.
SheetTitleDialogPrimitive.Title—Accessible name for the panel. Required for screen-reader announcements.
SheetDescriptionDialogPrimitive.Description—Supporting text linked to the panel via aria-describedby.
SheetFooterdiv—Bottom region for actions: mt-auto pins it to the base of the panel, p-4 matches the header.
SheetCloseDialogPrimitive.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.
  • On close, focus returns to the SheetTrigger — or, with no Trigger, to the element that had focus just before the panel opened. That second half is the package’s, since 3.3.0; it is how the shell’s MobileMenu, which the header’s menu button opens from state, hands focus back to that button. The rules are Dialog’s: a DropdownMenu item resolves to the menu’s trigger button, an opener that is gone gets no guess, and your own onCloseAutoFocus runs first and wins.
  • Always include a SheetTitle — it provides the aria-labelledby name announced to screen readers; SheetDescription wires up aria-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, “Close” by default and “Đóng” under a Vietnamese ComitorLocaleProvider. A screen reader can meet that button out of context, so name the panel when it matters — the shell's MobileMenu passes its own “Close menu” for exactly that reason.
  • Content outside the open panel is inert and hidden from assistive technology, keeping keyboard navigation scoped to the sheet.