Rime

Sheet and Drawer

A panel that slides in from an edge over a scrim, and a bottom Drawer with a drag handle.

Sheet is a dialog flush to one edge (side: right, left, top or bottom) for secondary tasks that keep the page in view: a record's details, filters, settings. It traps focus, locks page scroll, closes on Esc, the scrim and the close button, and returns focus to whatever opened it.

Drawer is the bottom sheet, centred to a readable width on wide screens, with a grab handle. With dragToClose (on by default) a downward drag on the handle past about a third of its height dismisses it.

The header keeps one left edge: title and description stacked flush left, the close button at the right. The body scrolls on its own with the themed scrollbar; footer buttons sit along the bottom edge, primary last. Size is size (any CSS length) or --sheet-size.

inline renders the open panel in the page flow: no portal, scrim, focus trap, scroll lock or outside-click listener. It exists for docs, previews and static mock-ups; never ship it as the live overlay.

Installation

npx shadcn@latest add KezLahd/rime/sheet

Also installs: alert-dialog, base, icon, icon-button, scroll-area.

Usage

import { Button, Drawer, Sheet } from "@/components/ui";

<Sheet
  open={open}
  onClose={() => setOpen(false)}
  title="Edit team member"
  footer={<Button onClick={save}>Save changes</Button>}
>
  …fields…
</Sheet>

Examples

Open

The panel itself, drawn inline.

From each edge

Drawer, open

Drawer with drag to close

Drag the handle down to dismiss.

API

Generated from the component's TypeScript types and JSDoc (scripts/gen-ui-registry.mjs), so it always matches the source.

Sheet

Sheet props
PropTypeDefaultDescription
openRequiredboolean
onCloseRequired() => voidEsc, the scrim and the close button.
titleRequiredReactNode
descriptionReactNode
childrenReactNode
footerReactNodeButtons along the bottom edge, primary last.
sideSheetSide"right"The edge it slides in from.
sizestringWidth (left, right) or height (top, bottom), any CSS length. Defaults to --sheet-size, 420px.
closeLabelstring"Close"
inlinebooleanRender the open panel in the page flow: no portal, scrim, focus trap or scroll lock (docs, previews).
classNamestring

Drawer

Drawer props
PropTypeDefaultDescription
footerReactNodeButtons along the bottom edge, primary last.
titleRequiredReactNode
classNamestring
childrenReactNode
openRequiredboolean
onCloseRequired() => voidEsc, the scrim and the close button.
descriptionReactNode
closeLabelstring
inlinebooleanRender the open panel in the page flow: no portal, scrim, focus trap or scroll lock (docs, previews).
dragToClosebooleantrueLet a downward drag on the handle dismiss it. On by default.

Theme tokens

Per-component tokens are undeclared by default, so the default shown is the fallback the CSS uses. Set one at :root (or in theme.css) to restyle every instance. Live values are read from this page, so they follow the Rime Studio.

Sheet and Drawer per-component tokens
TokenDefaultLive value
--drawer-width640px…
--sheet-radiusvar(--r-xl)…
--sheet-size420px / 85dvh / 380px…
--sheet-title-size18px…

System tokens it reads

Sheet and Drawer system tokens
TokenDefaultLive value
--border-wtokens.css…
--densitytokens.css…
--durtokens.css…
--easetokens.css…
--ease-outtokens.css…
--font-displaytokens.css…
--ink-bodytokens.css…
--ink-headingtokens.css…
--ink-secondarytokens.css…
--line-glasstokens.css…
--modal-blurtokens.css…
--modal-scrimtokens.css…
--modal-scrim-blurtokens.css…
--modal-shadowtokens.css…
--modal-surfacetokens.css…
--r-fulltokens.css…
--r-xltokens.css…
--rgb-brand-deeptokens.css…
--text-smalltokens.css…
--tracking-displaytokens.css…
--z-modaltokens.css…

Accessibility

  • role="dialog" with aria-modal, labelled by the title and described by the description.
  • Focus moves in on open, Tab is trapped, Esc closes, and focus returns to the opener. The drag handle is pointer-only; Esc and the close button are always there.
  • Reduced motion: it fades in place instead of sliding.

Do and don't

Do

  • Use a right sheet for detail and edit panels, a bottom drawer on phones.
  • Keep one primary action in the footer.

Don't

  • Don't stack a sheet on a modal.
  • Don't hide navigation in a sheet on desktop; that is the sidebar.

For AI agents

This page as markdown, rendered from the same registry entry. Point an agent at it (or add .md to this page's URL), or at /llms.txt for the index.

Open sheet.md

Related: modal, alert-dialog