# Drawer and Sheet

> Drawer and Sheet: anatomy, keyboard behavior, state, and theming in Askr.

Source: [https://askrjs.com/docs/components/drawer-and-sheet](https://askrjs.com/docs/components/drawer-and-sheet)

Status: experimental. Packages: @askrjs/themes/drawer, @askrjs/themes/sheet.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

```tsx
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>
```

## Purpose

Drawer and Sheet are themed components for panel-style overlays — a drawer sliding in from an edge, a sheet covering more of the viewport — but as shipped today they're both exported as direct aliases of `Dialog` under `@askrjs/themes`, with no headless `@askrjs/ui` primitive of their own. That's why this page is marked experimental: the names exist to signal intent in your markup, but the underlying behavior, positioning, and CSS are currently identical to Dialog.

## Install and import

Headless control for these components comes from `@askrjs/ui/dialog` — no separate `@askrjs/ui/drawer` or `@askrjs/ui/sheet` package exists. Themed usage is different: import from `@askrjs/themes/drawer` and `@askrjs/themes/sheet`, which compile to the same output as `@askrjs/themes/dialog` under the hood. The only visible difference is naming — you'll get `Drawer`/`Sheet`-prefixed exports such as `DrawerContent` and `SheetTrigger` instead of `Dialog`-prefixed ones.

## Live examples

A Drawer or Sheet example looks exactly like a Dialog example with the names swapped: a root component wrapping a trigger and a portal-rendered content block with title, description, and close affordances. There is currently no `side` prop or edge-anchored slide-in animation distinguishing them visually from a centered modal — that's the clearest way to see the alias in practice.

## Anatomy

`DrawerContent`/`SheetContent` are `DialogContent` under a different name, so they inherit the same overlay-plus-content structure: `DrawerTrigger` opens it, `DrawerPortal` mounts it outside the normal DOM flow, `DrawerOverlay` is the backdrop, and `DrawerTitle`/`DrawerDescription` supply the accessible name and description. Swap the `Drawer` prefix for `Sheet` and the story is identical.

## State model

Open state follows Dialog's shape exactly: `open`, `defaultOpen`, `onOpenChange`, and `modal` on the root component. There is no drawer-specific state, like which edge it's anchored to, because that behavior hasn't been built out separately from Dialog yet.

## Keyboard and accessibility

Because the implementation is Dialog's, Escape-to-close, focus trapping, and the `dialog`/`alertdialog` role handling all carry over unchanged — `DialogContentOwnProps`' `onEscapeKeyDown`, `onPointerDownOutside`, and `onDismiss` hooks are available under the Drawer/Sheet names too. Don't assume drawer-specific screen-reader behavior (like announcing a direction of entry) exists; it doesn't yet.

## Styling and tokens

There's no dedicated `drawer.css` or `sheet.css` in the default theme — both ride on the same overlay CSS and `data-state`/`data-slot` attributes as Dialog. If you want an actual slide-in panel from an edge, you'll need to add that positioning and transition CSS yourself against the Dialog-derived markup, since the shipped styles only render it as a centered modal.

## API

The full Dialog prop surface is inherited: `DrawerContent`/`SheetContent` take `forceMount`, `role`, `onEscapeKeyDown`, `onPointerDownOutside`, `onInteractOutside`, and `onDismiss`; `DrawerTrigger`/`SheetTrigger` and `DrawerClose`/`SheetClose` take standard button-like props. There are no drawer- or sheet-specific props like `side` or `size` in the current release.

## Edge cases

If your design calls for a genuine edge-anchored panel with its own slide transition, treat Drawer and Sheet as a naming convention today, not a distinct component — you're responsible for the positioning CSS and any width/height constraints. Because both names compile to the same module as Dialog, mixing `Drawer` and `Sheet` imports in one tree carries no behavioral risk, but it also means renaming one to the other later is a no-op beyond your own class names.

## Related pages

See Dialog for the primitive Drawer and Sheet are currently built from, including its full controlled-state and dismissal-handling API. See Alert Dialog for the confirmation-flow variant of the same underlying pattern.

## Documentation navigation

[Previous](https://askrjs.com/docs/components/menu-dropdown-and-context-menu/index.md) | [Next](https://askrjs.com/docs/components/menubar/index.md)
