Sheet
Sheet: anatomy, keyboard behavior, state, and theming in Askr.
Example
import { Button, Sheet, SheetClose, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from '@askrjs/themes/components';
<Sheet>
<SheetTrigger asChild><Button variant="outline">Open filters</Button></SheetTrigger>
<SheetContent>
<SheetTitle>Project filters</SheetTitle>
<SheetDescription>Narrow the project list without leaving the page.</SheetDescription>
<ProjectFilters />
<SheetClose>Apply filters</SheetClose>
</SheetContent>
</Sheet>Published props
Generated from the TypeScript declarations shipped by the installed package. Named types in the Type column define the accepted values.
DialogCloseAsChildProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild: true; | — | — |
children | children: JSXElement; | — | — |
disabled | disabled?: boolean | undefined; | — | — |
onPress | onPress?: ((event: PressEvent) => void) | undefined; | — | — |
ref | ref?: Ref<Element>; | — | — |
type | type?: undefined; | — | — |
DialogCloseProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild?: false | undefined; | — | — |
children | children?: unknown; | — | — |
disabled | disabled?: boolean | undefined; | — | — |
onPress | onPress?: ((event: PressEvent) => void) | undefined; | — | — |
ref | ref?: Ref<HTMLButtonElement>; | — | — |
type | type?: "button" | "submit" | "reset" | undefined; | — | — |
DialogContentAsChildProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild: true; | — | — |
children | children: JSXElement; | — | — |
forceMount | forceMount?: boolean | undefined; | — | — |
onDismiss | onDismiss?: (() => void) | undefined; | — | — |
onEscapeKeyDown | onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined; | — | — |
onInteractOutside | onInteractOutside?: ((event: Event) => void) | undefined; | — | — |
onPointerDownOutside | onPointerDownOutside?: ((event: PointerEvent) => void) | undefined; | — | — |
ref | ref?: Ref<Element>; | — | — |
restoreFocus | restoreFocus?: HTMLElement | (() => HTMLElement | null) | null | undefined; | — | Explicit focus target used when a controlled dialog has no persistent trigger. |
role | role?: "dialog" | "alertdialog" | undefined; | — | — |
DialogContentOwnProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | forceMount?: boolean | undefined; | — | — |
onDismiss | onDismiss?: (() => void) | undefined; | — | — |
onEscapeKeyDown | onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined; | — | — |
onInteractOutside | onInteractOutside?: ((event: Event) => void) | undefined; | — | — |
onPointerDownOutside | onPointerDownOutside?: ((event: PointerEvent) => void) | undefined; | — | — |
restoreFocus | restoreFocus?: HTMLElement | (() => HTMLElement | null) | null | undefined; | — | Explicit focus target used when a controlled dialog has no persistent trigger. |
role | role?: "dialog" | "alertdialog" | undefined; | — | — |
DialogContentProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild?: false | undefined; | — | — |
children | children?: unknown; | — | — |
forceMount | forceMount?: boolean | undefined; | — | — |
onDismiss | onDismiss?: (() => void) | undefined; | — | — |
onEscapeKeyDown | onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined; | — | — |
onInteractOutside | onInteractOutside?: ((event: Event) => void) | undefined; | — | — |
onPointerDownOutside | onPointerDownOutside?: ((event: PointerEvent) => void) | undefined; | — | — |
ref | ref?: Ref<HTMLDivElement>; | — | — |
restoreFocus | restoreFocus?: HTMLElement | (() => HTMLElement | null) | null | undefined; | — | Explicit focus target used when a controlled dialog has no persistent trigger. |
role | role?: "dialog" | "alertdialog" | undefined; | — | — |
DialogDescriptionAsChildProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild: true; | — | — |
children | children: JSXElement; | — | — |
ref | ref?: Ref<Element>; | — | — |
DialogDescriptionProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild?: false | undefined; | — | — |
children | children?: unknown; | — | — |
ref | ref?: Ref<HTMLParagraphElement>; | — | — |
DialogOverlayAsChildProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild: true; | — | — |
children | children: JSXElement; | — | — |
forceMount | forceMount?: boolean | undefined; | — | — |
ref | ref?: Ref<Element>; | — | — |
DialogOverlayOwnProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | forceMount?: boolean | undefined; | — | — |
DialogOverlayProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild?: false | undefined; | — | — |
children | children?: unknown; | — | — |
forceMount | forceMount?: boolean | undefined; | — | — |
ref | ref?: Ref<HTMLDivElement>; | — | — |
DialogOwnProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
children | children?: unknown; | — | — |
defaultOpen | defaultOpen?: boolean | undefined; | — | — |
id | id?: string | undefined; | — | — |
modal | modal?: boolean | undefined; | — | — |
onOpenChange | onOpenChange?: ((open: boolean) => void) | undefined; | — | — |
open | open?: boolean | undefined; | — | — |
DialogPortalProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
children | children?: unknown; | — | — |
DialogProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
children | children?: unknown; | — | — |
defaultOpen | defaultOpen?: boolean | undefined; | — | — |
id | id?: string | undefined; | — | — |
modal | modal?: boolean | undefined; | — | — |
onOpenChange | onOpenChange?: ((open: boolean) => void) | undefined; | — | — |
open | open?: boolean | undefined; | — | — |
DialogTitleAsChildProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild: true; | — | — |
children | children: JSXElement; | — | — |
ref | ref?: Ref<Element>; | — | — |
DialogTitleProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild?: false | undefined; | — | — |
children | children?: unknown; | — | — |
ref | ref?: Ref<HTMLHeadingElement>; | — | — |
DialogTriggerAsChildProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild: true; | — | — |
children | children: JSXElement; | — | — |
disabled | disabled?: boolean | undefined; | — | — |
onPress | onPress?: ((event: PressEvent) => void) | undefined; | — | — |
ref | ref?: Ref<Element>; | — | — |
type | type?: undefined; | — | — |
DialogTriggerProps
Import from @askrjs/ui/dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | asChild?: false | undefined; | — | — |
children | children?: unknown; | — | — |
disabled | disabled?: boolean | undefined; | — | — |
onPress | onPress?: ((event: PressEvent) => void) | undefined; | — | — |
ref | ref?: Ref<HTMLButtonElement>; | — | — |
type | type?: "button" | "submit" | "reset" | undefined; | — | — |
Purpose
Sheet provides a themed edge panel built on Dialog behavior. Its content adds side positioning and Sheet-specific slots, while Dialog remains the owner of open state, focus and dismissal.
Install and import
Import Sheet and its parts from @askrjs/themes/sheet or the supported @askrjs/themes/components aggregate. Its headless behavior comes from @askrjs/ui/dialog. For 0.5, migrate retired Drawer aliases to the corresponding Dialog components; use Sheet when its side positioning is intended.
Live examples
Open the Sheet example and inspect its edge positioning and accessible title. Set side="left" on SheetContent to move it to the left edge, then close it and verify focus returns to the trigger.
Anatomy
Sheet composes Sheet, SheetTrigger, SheetPortal, SheetOverlay and SheetContent with SheetTitle, SheetDescription and SheetClose. Root, trigger, portal, overlay and close reuse Dialog; the themed content and text parts provide Sheet-specific slots.
State model
Open state is owned by the Dialog-derived Sheet root through open, defaultOpen and onOpenChange. The SheetContent side prop is presentation input and does not create another state store.
Keyboard and accessibility
Sheet inherits Dialog focus and dismissal behavior. Verify Escape, outside interactions, accessible title and description, and return focus through your composed trigger and content. The side prop does not add gesture or directional screen-reader semantics.
Styling and tokens
The default overlay stylesheet targets data-slot="sheet-content" and data-side for edge positioning. SheetHeader, SheetFooter, SheetTitle and SheetDescription expose their own slots; theme tokens control the shared surface, border and motion presentation.
API
Sheet accepts the Dialog root props open, defaultOpen, onOpenChange and modal. SheetContent adds side="top" | "right" | "bottom" | "left", defaulting to right, and forwards its remaining props to DialogContent. SheetHeader and SheetFooter provide layout slots.
Edge cases
Test the chosen side at narrow widths and with long content. Sheet relies on Dialog for focus and dismissal; side changes presentation rather than creating another open-state owner. Provide an accessible title and an explicit close action.
Related pages
See Dialog for the underlying open-state, focus and dismissal model, and Alert Dialog for confirmation flows.