Skip to content

Now in the official shadcn registry directory.

Start free

Sheet

A slide-in panel on the radix Dialog primitive - pick one of four sides and get directional slide animations driven by the ai2 motion tokens.

overlay
A free styled version is available

Installation

Run the following command

npx shadcn@latest add @ai2/sheet

Dependencies, the @ai2/tokens theme and the component file are installed together.

Usage

TS
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"

<Sheet>
  <SheetTrigger asChild>
    <Button variant="outline">Open sheet</Button>
  </SheetTrigger>
  <SheetContent side="right">
    <SheetHeader>
      <SheetTitle>Deployment details</SheetTitle>
      <SheetDescription>dep_8f3k2m · us-east-1 · ready</SheetDescription>
    </SheetHeader>
  </SheetContent>
</Sheet>

Set side on SheetContent. Use left/right for navigation drawers and detail panels, bottom for mobile filters.

Examples

Sides

SheetFooter uses mt-auto to pin its actions to the bottom of the panel; SheetClose asChild dismisses without extra state.

Sizes

The size prop sets the panel width for side="left" and side="right" from the sm breakpoint up: sm (max-w-xs), md (the default, max-w-sm) and lg (max-w-md). On mobile those panels stay w-3/4. For side="top" and side="bottom" the size prop is a no-op, since those bars are always full width and size to their content.

Props

SheetContent adds two props; every part also forwards its underlying radix Dialog props - e.g. open / onOpenChange on Sheet.

PropTypeDefaultDescription
side"right" | "left" | "top" | "bottom""right"Edge the panel slides in from. Left/right are full-height columns; top/bottom are full-width bars.
size"sm" | "md" | "lg""md"Panel width for side left/right from the sm breakpoint up: sm (max-w-xs), md (max-w-sm), lg (max-w-md). On mobile left/right stay w-3/4. No-op for side top/bottom, which are always full width and size to their content.

ai2 Sheet: a side drawer for React, sliding from any edge

The ai2 Sheet is a shadcn-compatible sheet component for React, built on the radix-ui Dialog primitive and styled with Tailwind CSS v4. It is the classic side drawer: a panel that slides in from the right, left, top or bottom edge of the screen over a dimmed overlay, ideal for navigation menus, detail panels, edit forms and mobile filters.

It ships through the shadcn registry format, so one CLI command, an MCP agent, or a copy-paste puts the source in your own project. You own the file; there is no runtime dependency on ai2 itself. The live example above is the exact component you get.

What is the ai2 Sheet?

It is an eight-part composition: Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter and SheetClose. The anatomy matches shadcn/ui exactly, so existing snippets and AI agents keep working without changes.

Under the hood it is a radix Dialog: the panel renders in a portal over a fixed overlay, traps focus while open, and closes on Escape or an overlay click. The two styling decisions you make are the side prop, which picks one of four directional slide animations driven by the shared ai2 motion tokens, and the size prop, which sets the panel width for the left and right sides.

Why use it

  • Four sides from one prop: side="right" (the default), left, top or bottom. Left and right are full-height columns whose desktop width is set by the size prop (sm, md, lg); top and bottom are full-width bars that size to their content.
  • Accessible by construction: The radix Dialog primitive provides focus trapping, aria-labelledby wiring via SheetTitle, aria-describedby via SheetDescription, Escape to close and focus return to the trigger.
  • Motion from tokens: The slide and fade animations read --motion-base and --motion-ease from the shared token file, so the drawer moves at the same tempo as every other ai2 component.
  • Built-in close button: SheetContent renders an X button in the top right corner with a screen-reader-only "Close" label and a focus-visible ring, so every sheet is dismissable without extra code.
  • Controlled or uncontrolled: Let SheetTrigger manage the open state, or pass open and onOpenChange to the root to drive the drawer from router state or a keyboard shortcut.

Features

  • shadcn registry install: One command adds the component, its dependencies and the @ai2/tokens theme to your project.
  • Directional slide animations: Each side pairs slide-in-from and slide-out-to keyframes with a fading overlay, so open and close both read as one continuous movement.
  • Header and footer slots: SheetHeader stacks the title and description; SheetFooter uses mt-auto to pin actions to the bottom edge of the panel regardless of content height.
  • Portal rendering: The overlay and panel render in a portal at z-50, so the sheet escapes any overflow or stacking context in the surrounding layout.
  • Data attributes for styling: Every part exposes data-slot, and the panel exposes data-state for open and closed, so you can restyle states from CSS without forking the component.
  • TypeScript source: The file you install is typed end to end and forwards every radix Dialog prop, so autocomplete covers the full API.

Production tips

  • Always include SheetTitle: The title is what radix announces as the dialog's accessible name. If you want a visually clean panel, keep the title and hide it with sr-only instead of omitting it.
  • Match side to the use case: Right suits detail panels and edit forms, left suits navigation, bottom suits mobile filter and action sheets. Top works best for short announcements or search bars.
  • Use SheetClose for cancel actions: Wrap your Cancel button in SheetClose asChild instead of wiring onOpenChange manually. It dismisses the sheet and keeps focus management intact.
  • Mind the width on desktop: Left and right panels are w-3/4, capped from the sm breakpoint at a width set by the size prop: sm (max-w-xs), md (the default, max-w-sm) or lg (max-w-md). For content wider than lg, override the max width on SheetContent via className rather than fighting the layout inside.
  • Do not nest heavy forms without scroll: The panel is a flex column with p-6. If a form can outgrow the viewport, add overflow-y-auto to a wrapper inside the content so the header and footer stay visible.

Works with the rest of ai2

The sheet composes naturally with the rest of the registry. Use an ai2 Button as the trigger and for footer actions, lay out edit forms inside with ai2 Field and ai2 Input rows, and divide long panels with an ai2 Separator.

When the surface should sit in the center of the screen instead of an edge, reach for Dialog instead: both share the same radix primitive and anatomy, so switching between them is mostly a rename. Everything reads one token source, so combinations stay consistent in both light and dark mode.

FAQs

Get new components in your inbox

Component drops, new themes and release notes. No spam, and you can unsubscribe from any email.

© 2026 ai2 design system · MIT licensed · Built with its own components