Skip to content

Drawer & Sheet

Two edge-anchored surfaces. Drawer slides in from left or right for navigation and secondary panels on wide screens. BottomSheet rises from the bottom on touch — drag between snap points, fling down to dismiss. Both scrim and blur the content behind them.

Drawer — open states

Drawer is position:fixed without a portal, so these specimens capture the genuinely open drawer inside a transformed box (the transform makes the box its containing block). In product it spans the full viewport edge.

Open — side=right (default)
Open — side=left
Non-dismissable

dismissable={false} — backdrop clicks ignored; ceremonies exit only through an explicit action.

Closed → open (live)

Escape or backdrop click dismisses.

import { Drawer } from "@coldharbor/ui";

<Drawer
  open={menuOpen}
  onOpenChange={setMenuOpen}
  side="right"
  ariaLabel="Wallet menu"
>
  <WalletMenu />
</Drawer>
  • --ch-bg
  • --ch-border
  • --ch-fg
  • --ch-fg-muted
  • --ch-overlay
  • --ch-primary

BottomSheet

The sheet portals to <body> unconditionally (fixed positioning must escape transformed ancestors on mobile), so the open state is a static replica with the exact surface, grab handle and header; the live specimen opens the real sheet.

Open at snap 50% (static replica)

Replica — the real sheet cannot render inline.

Live

Opens over the page (portalled). Snap points 50% and 92% of the viewport; drag the handle or fling down to dismiss.

Drag the handle up to the 92% snap; fling down to dismiss.

import { BottomSheet } from "@coldharbor/ui";

<BottomSheet
  open={feeSheetOpen}
  onOpenChange={setFeeSheetOpen}
  title="Fee options"
  description="Higher rates confirm sooner. You can bump later with RBF."
  snapPoints={[0.5, 0.92]}
>
  <FeeOptions />
</BottomSheet>
  • --ch-bg
  • --ch-border
  • --ch-fg
  • --ch-fg-muted
  • --ch-overlay
  • --ch-primary

Themes

The open sheet replica under all three layers.

  • --ch-bg
  • --ch-border
  • --ch-fg
  • --ch-fg-muted
  • --ch-overlay
  • --ch-primary