Sheet
A panel that slides in from an edge of the screen for work beside the page, such as filters or details.
A sheet is a dialog shaped as a panel along an edge of the screen. Use it for a task that belongs to the page but needs room: filters, the details of a row, a short form. The page stays visible behind it. On a phone, consider a drawer, which can be swiped away.
Showing: Active
// apps/docs/examples/ui/sheet.tsx'use client';
import {useState} from 'react';
import {Button} from '@workspace/active-ui/components/primitives/button';import {Checkbox} from '@workspace/active-ui/components/primitives/checkbox';import { Field, FieldGroup, FieldLabel,} from '@workspace/active-ui/components/primitives/field';import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger,} from '@workspace/active-ui/components/primitives/sheet';
const SIDES = ['right', 'left', 'top', 'bottom'] as const;const STATUSES = ['Active', 'Paused', 'Closed'];
/** * A panel that slides in from an edge, for work beside the page: here a set * of filters that applies only when the reader confirms. The panel keeps its * own draft; `SheetClose` closes it from the footer buttons. */export default function SheetExample() { const [side, setSide] = useState<(typeof SIDES)[number]>('right'); const [applied, setApplied] = useState<string[]>(['Active']); const [draft, setDraft] = useState<string[]>(applied); return ( <div className="flex flex-col items-center gap-4"> <div className="flex flex-wrap justify-center gap-2"> {SIDES.map((option) => ( <Sheet key={option} onOpenChange={(open) => { if (open) { setSide(option); setDraft(applied); } }} > <SheetTrigger render={<Button variant="outline" />}> Filters ({option}) </SheetTrigger> <SheetContent side={side} closeLabel="Close filters"> <SheetHeader> <SheetTitle>Filter schemes</SheetTitle> <SheetDescription> Show only the schemes with these statuses. </SheetDescription> </SheetHeader> <FieldGroup className="gap-3 px-4"> {STATUSES.map((status) => ( <Field key={status} orientation="horizontal"> <Checkbox id={`sheet-${option}-${status}`} checked={draft.includes(status)} onCheckedChange={(checked) => setDraft((current) => checked ? [...current, status] : current.filter((value) => value !== status), ) } /> <FieldLabel htmlFor={`sheet-${option}-${status}`}> {status} </FieldLabel> </Field> ))} </FieldGroup> <SheetFooter> <SheetClose render={<Button />} onClick={() => setApplied(draft)} > Apply filters </SheetClose> <SheetClose render={<Button variant="outline" />}> Cancel </SheetClose> </SheetFooter> </SheetContent> </Sheet> ))} </div> <p className="text-muted-foreground text-sm"> Showing: {applied.length ? applied.join(', ') : 'nothing'} </p> </div> );}Usage#
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger,} from '@workspace/active-ui/components/primitives/sheet';
<Sheet> <SheetTrigger render={<Button variant="outline" />}>Filters</SheetTrigger> <SheetContent side="right" closeLabel="Close filters"> <SheetHeader> <SheetTitle>Filter schemes</SheetTitle> <SheetDescription> Show only the schemes with these statuses. </SheetDescription> </SheetHeader> </SheetContent></Sheet>;Anatomy#
Sheet: the open state;openandon, or uncontrolled.Open Change SheetandTrigger Sheet: open and close from any element (Close renderfor your own).Sheet: the panel with its backdrop.Content side:right(the default),left,toporbottom. A side panel is three quarters of the screen wide up to24rem; a top or bottom one as high as its content.SheetwithHeader SheetandTitle Sheet;Description Sheetat the bottom of the panel, for its actions.Footer
What your application provides#
close: the accessible name of the close button in the corner. It is required while the button is shown and not allowed withLabel show.Close Button={false} The title, description and content, and what the actions do. A sheet that edits something keeps a draft and applies it on confirm, as the example does; a sheet that only shows something needs no footer.
Accessibility and keyboard#
A modal dialog: the focus moves inside on open and stays there; the page behind is inert.
Escapeand a click on the backdrop close it; the focus returns to the trigger.The panel is named by its title and described by its description.
API#
SheetContent#
Import from @workspace/
Props marked Base UI are behaviour of the Base UI part this component is built on.
Props
- Type
string
The accessible name of the close button; required while it is shown.
- Type
booleanRefObject<HTMLElement | null> (closeType) => โฆ
Determines the element to focus when the dialog is closed.
false: Do not move focus.true: Move focus based on the default behavior (trigger or previously focused element).Ref: Move focus to the ref element.Object function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior,nullto fall back to the default behavior, orfalse/undefinedto do nothing.
- Type
booleanRefObject<HTMLElement | null> (openType) => โฆ
Determines the element to focus when the dialog is opened. By default, focus moves to the first tabbable element inside the popup, except when the dialog is opened by touch โ then the popup itself is focused to avoid opening the virtual keyboard.
false: Do not move focus.true: Move focus based on the default behavior (first tabbable element or popup).Ref: Move focus to the ref element.Object function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior,nullto fall back to the default behavior, orfalse/undefinedto do nothing.
- Type
"bottom""left""right""top"- Default
'right'
The edge the sheet slides in from.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Other parts#
Sheet
All props come from the Base UI part this component is built on.
Props
- Type
boolean
Whether the dialog is currently open.
- Type
boolean- Default
false
Whether the dialog is initially open.
To render a controlled dialog, use the open prop instead.
- Type
PayloadChild Render Function<โฆ> ReactNode
The content of the dialog. This can be a regular React node or a render function that receives the payload of the active trigger.
- Type
string | null
ID of the trigger that the dialog is associated with. This is useful in conjunction with the default prop to create an initially open dialog.
- Type
boolean- Default
false
Whether to prevent the dialog from closing on outside presses. For non-modal dialogs, this also prevents the dialog from closing when focus moves outside of it.
- Type
DialogHandle<unknown>
A handle to associate the dialog with a trigger. If specified, allows external triggers to control the dialog's open state. Can be created with the Dialog.createHandle() method.
- Type
"trap-focus" | boolean - Default
true
Determines if the dialog enters a modal state when open.
true: user interaction is limited to just the dialog: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled.false: user interaction with the rest of the document is allowed.'trap-: focus is trapped inside the dialog, but document page scroll is not locked and pointer interactions outside of it remain enabled.focus'
When modal is true or 'trap-, render <Dialog. inside <Dialog. so touch screen readers can escape the popup.
- Type
string | null
ID of the trigger that the dialog is associated with. This is useful in conjunction with the open prop to create a controlled dialog. There's no need to specify this prop when the dialog is uncontrolled (that is, when the open prop is not set).
- Type
RefObject<โฆ>
A ref to imperative actions.
unmount: Ends the closing phase of the dialog after an externally controlled closing animation finishes. CallpreventinUnmount On Close() onfirst, otherwise the dialog completes closing on its own. Whether it leaves the DOM is decided byOpen Change keepon the portal.Mounted close: Closes the dialog imperatively when called.
Events
Called by the component when something happens.
- Type
(open, eventDetails) => void
Event handler called when the dialog is opened or closed.
- Type
(open: boolean) => void
Event handler called after any animations complete when the dialog is opened or closed.
Takes only the props listed.
SheetTrigger
All props come from the Base UI part this component is built on.
Props
- Type
DialogHandle<unknown>
A handle to associate the trigger with a dialog. Can be created with the Dialog.createHandle() method.
- Type
string
ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for the dialog in controlled mode (with the DialogRoot trigger prop).
- Type
unknown
A payload to pass to the dialog when it is opened.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
SheetClose
All props come from the Base UI part this component is built on.
Props
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Parts that take only their elementโs attributes
Sheet: the attributes of aHeader <div>, with className and ref.Sheet: the attributes of its element, with className and ref, and Base UI'sTitle renderto use your own element.Sheet: the attributes of its element, with className and ref, and Base UI'sDescription renderto use your own element.
This page adapts the Sheet documentation of shadcn/ui (MIT licence) to this package; see Third-party notices.