Skip to content

Components · Sheet

Sheet

A side-anchored panel for settings, filters, details and navigation. It is built on the same Radix Dialog primitive as Dialog, so focus trapping, focus restore, Escape and overlay behaviour are the mature ones LUC already ships. A gesture drawer is deliberately out of scope: a Sheet is a panel, not a swipeable card.

Examples

import { Sheet, SheetBody, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@luc/ui";

Edges

Four edges, one surface. Choose the edge by what the panel is for: right for settings and details, left for navigation, bottom for filters on small screens.

Behaviour that comes for free

Inherited from the Dialog primitive, not re-invented here.

  • Focus is trapped inside the panel and returned to the trigger on close.
  • Escape closes; the overlay absorbs the click and the page behind never scrolls away.
  • The panel is a labelled dialog, so screen readers announce it by its title.
  • Under reduced motion the slide collapses to an immediate appearance.
// Sizes are a vocabulary, not a free-for-all: sm, md, lg, xl, full. // Widths for left/right edges, heights for top/bottom.

API

Read from the published TypeScript API, so a prop that is not listed here does not exist and a default that is listed is the one the compiler sees.

Exported symbols
ExportKindSignature
Sheet5 documented props({ open, defaultOpen, onOpenChange, children, ...props }: SheetRootProps) => import("@types/react").JSX.Element
SheetBodyexport({ className, ...props }: React.ComponentPropsWithRef<"div">) => import("@types/react").JSX.Element
SheetClose1 documented propsimport("@types/react").ForwardRefExoticComponent<RadixDialog.DialogCloseProps & import("@types/react").RefAttributes<HTMLButtonElement>>
SheetContent12 documented props({ className, children, side, size, showClose, onOpenAutoFocus, onCloseAutoFocus, ...props }: SheetContentProps) => import("@types/react").JSX.Element
SheetDescription1 documented propsimport("@types/react").ForwardRefExoticComponent<RadixDialog.DialogDescriptionProps & import("@types/react").RefAttributes<HTMLParagraphElement>>
SheetFooterexport({ className, ...props }: React.ComponentPropsWithRef<"div">) => import("@types/react").JSX.Element
SheetHeader1 documented props({ className, icon, children, ...props }: SheetHeaderProps) => import("@types/react").JSX.Element
SheetRoot5 documented props({ open, defaultOpen, onOpenChange, children, ...props }: SheetRootProps) => import("@types/react").JSX.Element
SheetTitle1 documented propsimport("@types/react").ForwardRefExoticComponent<RadixDialog.DialogTitleProps & import("@types/react").RefAttributes<HTMLHeadingElement>>
SheetTrigger1 documented propsimport("@types/react").ForwardRefExoticComponent<RadixDialog.DialogTriggerProps & import("@types/react").RefAttributes<HTMLButtonElement>>

Sheet props

Type: RadixDialog.DialogProps

Values the compiler reads from the declaration.

Sheet props
PropTypeDefaultNotes
children?inheritedReactNode—
defaultOpen?inheritedboolean | undefined—
modal?inheritedboolean | undefined—
onOpenChange?inherited((open: boolean) => void) | undefined—
open?inheritedboolean | undefined—

SheetClose props

Type: DialogCloseProps & RefAttributes<HTMLButtonElement>

Values the compiler reads from the declaration.

SheetClose props
PropTypeDefaultNotes
asChild?inheritedboolean | undefined—

SheetContent props

Type: SheetContentProps

Values the compiler reads from the declaration.

SheetContent props
PropTypeDefaultNotes
asChild?inheritedboolean | undefined—
deferPointerDownOutside?inheritedboolean | undefined—When `true`, a `'pointerdown'` event outside of the layered element will wait for the interaction's click event before dispatching, allowing third-party code to stop propagation o…
forceMount?inheritedtrue | undefined—Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.
onCloseAutoFocus?inherited((event: Event) => void) | undefined—Event handler called when auto-focusing on close. Can be prevented.
onEscapeKeyDown?inherited((event: KeyboardEvent) => void) | undefined—Event handler called when the escape key is down. Can be prevented.
onFocusOutside?inherited((event: FocusOutsideEvent) => void) | undefined—Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
onInteractOutside?inherited((event: PointerDownOutsideEvent | FocusOutsideEvent) => void) | undefined—Event handler called when an interaction happens outside the `DismissableLayer`. Specifically, when a `pointerdown` event happens outside or focus moves outside of it. Can be prev…
onOpenAutoFocus?inherited((event: Event) => void) | undefined—Event handler called when auto-focusing on open. Can be prevented.
onPointerDownOutside?inherited((event: PointerDownOutsideEvent) => void) | undefined—Event handler called when the a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
showClose?boolean | undefined—Show the built-in close affordance. Default `true`.
side?SheetSide | undefined—Edge the panel is anchored to. Default `right`.
size?SheetSize | undefined—Width (vertical edges) or height (horizontal edges). Default `md`.

SheetDescription props

Type: DialogDescriptionProps & RefAttributes<HTMLParagraphElement>

Values the compiler reads from the declaration.

SheetDescription props
PropTypeDefaultNotes
asChild?inheritedboolean | undefined—

SheetHeader props

Type: SheetHeaderProps

Values the compiler reads from the declaration.

SheetHeader props
PropTypeDefaultNotes
icon?ReactNode—

SheetRoot props

Type: RadixDialog.DialogProps

Values the compiler reads from the declaration.

SheetRoot props
PropTypeDefaultNotes
children?inheritedReactNode—
defaultOpen?inheritedboolean | undefined—
modal?inheritedboolean | undefined—
onOpenChange?inherited((open: boolean) => void) | undefined—
open?inheritedboolean | undefined—

SheetTitle props

Type: DialogTitleProps & RefAttributes<HTMLHeadingElement>

Values the compiler reads from the declaration.

SheetTitle props
PropTypeDefaultNotes
asChild?inheritedboolean | undefined—

SheetTrigger props

Type: DialogTriggerProps & RefAttributes<HTMLButtonElement>

Values the compiler reads from the declaration.

SheetTrigger props
PropTypeDefaultNotes
asChild?inheritedboolean | undefined—

Usage

import { SheetRoot, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetBody } from "@luc/ui/components/sheet";
<SheetRoot>
  <SheetTrigger asChild>
    <Button>Filters</Button>
  </SheetTrigger>
  <SheetContent side="right" size="md">
    <SheetHeader>
      <SheetTitle>Filters</SheetTitle>
    </SheetHeader>
    <SheetBody>…</SheetBody>
  </SheetContent>
</SheetRoot>

Guidelines

Do

  • Use `side="right"` for a settings or filter panel, `side="bottom"` for a mobile action sheet, and keep the body scrollable while the header stays put.
  • Keep `SheetTitle` in every sheet; it is the panel's accessible name as well as its heading.

Don't

  • Use a sheet for a short confirmation; `AlertDialog` says “this is a decision” in a way a panel does not.

Accessibility

The sheet is a modal dialog that enters from the side it will leave by. Focus moves into the panel, Tab stays inside it, Escape and the close control dismiss it, and focus returns to the trigger.

Luc UI v1.0Sheetdark theme