Askr documentation
UI & Componentsexperimental

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.

PropTypeDefaultDescription
asChildasChild: true;——
childrenchildren: JSXElement;——
disableddisabled?: boolean | undefined;——
onPressonPress?: ((event: PressEvent) => void) | undefined;——
refref?: Ref<Element>;——
typetype?: undefined;——

DialogCloseProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild?: false | undefined;——
childrenchildren?: unknown;——
disableddisabled?: boolean | undefined;——
onPressonPress?: ((event: PressEvent) => void) | undefined;——
refref?: Ref<HTMLButtonElement>;——
typetype?: "button" | "submit" | "reset" | undefined;——

DialogContentAsChildProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild: true;——
childrenchildren: JSXElement;——
forceMountforceMount?: boolean | undefined;——
onDismissonDismiss?: (() => void) | undefined;——
onEscapeKeyDownonEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;——
onInteractOutsideonInteractOutside?: ((event: Event) => void) | undefined;——
onPointerDownOutsideonPointerDownOutside?: ((event: PointerEvent) => void) | undefined;——
refref?: Ref<Element>;——
restoreFocusrestoreFocus?: HTMLElement | (() => HTMLElement | null) | null | undefined;—Explicit focus target used when a controlled dialog has no persistent trigger.
rolerole?: "dialog" | "alertdialog" | undefined;——

DialogContentOwnProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
forceMountforceMount?: boolean | undefined;——
onDismissonDismiss?: (() => void) | undefined;——
onEscapeKeyDownonEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;——
onInteractOutsideonInteractOutside?: ((event: Event) => void) | undefined;——
onPointerDownOutsideonPointerDownOutside?: ((event: PointerEvent) => void) | undefined;——
restoreFocusrestoreFocus?: HTMLElement | (() => HTMLElement | null) | null | undefined;—Explicit focus target used when a controlled dialog has no persistent trigger.
rolerole?: "dialog" | "alertdialog" | undefined;——

DialogContentProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild?: false | undefined;——
childrenchildren?: unknown;——
forceMountforceMount?: boolean | undefined;——
onDismissonDismiss?: (() => void) | undefined;——
onEscapeKeyDownonEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;——
onInteractOutsideonInteractOutside?: ((event: Event) => void) | undefined;——
onPointerDownOutsideonPointerDownOutside?: ((event: PointerEvent) => void) | undefined;——
refref?: Ref<HTMLDivElement>;——
restoreFocusrestoreFocus?: HTMLElement | (() => HTMLElement | null) | null | undefined;—Explicit focus target used when a controlled dialog has no persistent trigger.
rolerole?: "dialog" | "alertdialog" | undefined;——

DialogDescriptionAsChildProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild: true;——
childrenchildren: JSXElement;——
refref?: Ref<Element>;——

DialogDescriptionProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild?: false | undefined;——
childrenchildren?: unknown;——
refref?: Ref<HTMLParagraphElement>;——

DialogOverlayAsChildProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild: true;——
childrenchildren: JSXElement;——
forceMountforceMount?: boolean | undefined;——
refref?: Ref<Element>;——

DialogOverlayOwnProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
forceMountforceMount?: boolean | undefined;——

DialogOverlayProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild?: false | undefined;——
childrenchildren?: unknown;——
forceMountforceMount?: boolean | undefined;——
refref?: Ref<HTMLDivElement>;——

DialogOwnProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
childrenchildren?: unknown;——
defaultOpendefaultOpen?: boolean | undefined;——
idid?: string | undefined;——
modalmodal?: boolean | undefined;——
onOpenChangeonOpenChange?: ((open: boolean) => void) | undefined;——
openopen?: boolean | undefined;——

DialogPortalProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
childrenchildren?: unknown;——

DialogProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
childrenchildren?: unknown;——
defaultOpendefaultOpen?: boolean | undefined;——
idid?: string | undefined;——
modalmodal?: boolean | undefined;——
onOpenChangeonOpenChange?: ((open: boolean) => void) | undefined;——
openopen?: boolean | undefined;——

DialogTitleAsChildProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild: true;——
childrenchildren: JSXElement;——
refref?: Ref<Element>;——

DialogTitleProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild?: false | undefined;——
childrenchildren?: unknown;——
refref?: Ref<HTMLHeadingElement>;——

DialogTriggerAsChildProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild: true;——
childrenchildren: JSXElement;——
disableddisabled?: boolean | undefined;——
onPressonPress?: ((event: PressEvent) => void) | undefined;——
refref?: Ref<Element>;——
typetype?: undefined;——

DialogTriggerProps

Import from @askrjs/ui/dialog.

PropTypeDefaultDescription
asChildasChild?: false | undefined;——
childrenchildren?: unknown;——
disableddisabled?: boolean | undefined;——
onPressonPress?: ((event: PressEvent) => void) | undefined;——
refref?: Ref<HTMLButtonElement>;——
typetype?: "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.

See Dialog for the underlying open-state, focus and dismissal model, and Alert Dialog for confirmation flows.