Sheet

Side drawer built on Radix Dialog with a directional slide animation. Use for navigation, filters, quick edit, or any off-canvas panel.

Installation

pnpm
pnpm dlx @hex-core/cli add sheet

Bottom action sheet

Mobile-friendly Share-to surface using side="bottom" — three destinations as primary actions

tsx
<Sheet>
  <SheetTrigger asChild>
    <Button variant="outline">Share</Button>
  </SheetTrigger>
  <SheetContent side="bottom">
    <SheetHeader>
      <SheetTitle>Share to</SheetTitle>
      <SheetDescription>Pick where to send this link.</SheetDescription>
    </SheetHeader>
    <div className="grid grid-cols-3 gap-3 py-4">
      <Button variant="outline" onClick={() => shareTo("slack")}>Slack</Button>
      <Button variant="outline" onClick={() => shareTo("email")}>Email</Button>
      <Button variant="outline" onClick={() => shareTo("copy")}>Copy link</Button>
    </div>
  </SheetContent>
</Sheet>

Wide left navigation sheet

App-shell side nav for mobile — side="left" with a wider w-72 content panel and grouped sections

tsx
<Sheet>
  <SheetTrigger asChild>
    <Button variant="ghost" size="icon" aria-label="Open navigation">☰</Button>
  </SheetTrigger>
  <SheetContent side="left" className="w-72">
    <SheetHeader>
      <SheetTitle>Navigation</SheetTitle>
    </SheetHeader>
    <nav className="mt-4 space-y-6 text-sm">
      <div>
        <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">Workspace</p>
        <ul className="mt-2 space-y-1">
          <li><a href="/dashboard" className="block rounded px-2 py-1 hover:bg-accent">Dashboard</a></li>
          <li><a href="/projects" className="block rounded px-2 py-1 hover:bg-accent">Projects</a></li>
          <li><a href="/team" className="block rounded px-2 py-1 hover:bg-accent">Team</a></li>
        </ul>
      </div>
      <div>
        <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">Account</p>
        <ul className="mt-2 space-y-1">
          <li><a href="/settings" className="block rounded px-2 py-1 hover:bg-accent">Settings</a></li>
          <li><a href="/billing" className="block rounded px-2 py-1 hover:bg-accent">Billing</a></li>
        </ul>
      </div>
    </nav>
  </SheetContent>
</Sheet>

Variant values

sideWhich edge the sheet slides in from
ValueDescription
top
Slides down from the top edge
bottom
Slides up from the bottom edge
left
Slides in from the left edge
rightdefault
Slides in from the right edge (default)

API Reference

PropTypeDefaultDescription
open
booleanControlled open state
defaultOpen
booleanfalseDefault open state for uncontrolled usage
onOpenChange
functionCallback when open state changes: (open: boolean) => void
modal
booleantrueWhen true, content outside the sheet is inert

AI Guidance

When to use

Use for off-canvas panels — mobile nav menus, filter panels, side forms, detail views, or multi-step flows. Slides in from an edge, dismisses on outside click, Escape, or close button.

When not to use

Don't use for center-focused modals (use Dialog). Don't use for transient bottom sheets on mobile (use Drawer). Don't use for dropdown menus or quick popover actions (use DropdownMenu or Popover).

Common mistakes

  • Forgetting SheetTitle — Radix warns at runtime and screen readers announce an unnamed dialog
  • Putting a full page's content inside a sheet — too much friction; use a route instead
  • Overriding the side slide animation without matching the 'side' variant
  • Not handling controlled open state after SheetClose — use onOpenChange not manual state

Accessibility

Radix traps focus, handles Escape to close, and wires aria-labelledby/describedby to SheetTitle/Description. The Close button has sr-only text. Always include a SheetTitle.

Related components

Token budget: 700