Sheet
Side-anchored panel for longer flows, built on Radix Dialog with directional slide-in from any edge.
Overview
Sheet is a Radix Dialog stylized as a side panel. Use it for content that doesn't deserve full focus the way a Dialog does, but is too rich for a Popover: filter trays, detail panels, multi-section settings, navigation menus on mobile. Slide direction is configurable per side (top, right, bottom, left).
For desktop ergonomics, prefer right (filter and detail panels). left is conventional for navigation. On mobile breakpoints, Drawer is usually a better fit because it adds native drag-to-dismiss gestures.
Preview
'use client';import { Button } from '@gremorie/rx-forms';import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger,} from '@gremorie/rx-overlays';export function SheetPreview() { return ( <Sheet> <SheetTrigger asChild> <Button variant="outline">Open sheet</Button> </SheetTrigger> <SheetContent> <SheetHeader> <SheetTitle>Filters</SheetTitle> <SheetDescription> Narrow down the registry by category and edition. </SheetDescription> </SheetHeader> </SheetContent> </Sheet> );}Anatomy
Sheet Radix root holding open state
├─ SheetTrigger element that opens the sheet
└─ SheetContent portalled sliding panel (side, showCloseButton)
├─ SheetHeader wraps title + description
│ ├─ SheetTitle headline
│ └─ SheetDescription body text
├─ SheetClose closes the sheet
└─ SheetFooter bottom action rowInstallation
bash npx gremorie@latest add rx-sheet bash pnpm dlx gremorie@latest add rx-sheet bash yarn dlx gremorie@latest add rx-sheet bash bunx --bun gremorie@latest add rx-sheet Usage
import { Button } from "@gremorie/rx-forms";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@gremorie/rx-overlays";
export function Example() {
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="outline">Open filters</Button>
</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Filters</SheetTitle>
<SheetDescription>
Narrow down the registry by category and edition.
</SheetDescription>
</SheetHeader>
{/* filter controls */}
</SheetContent>
</Sheet>
);
}The Angular edition of this component ships from source today (see the workbench for the side-by-side); its registry entry is coming next.
API
<Sheet>
Extends Radix Dialog.Root. Same controlled API as Dialog (open, defaultOpen, onOpenChange, modal).
<SheetContent>
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" | Edge the sheet docks against and slides in from. |
showCloseButton | boolean | true | Renders the top-right X close button. |
Wraps Radix Dialog.Content in a Portal with the overlay. Width and height adapt to side:
right/left: full-height,w-3/4capped atsm:max-w-sm.top/bottom: full-width,h-auto.
<SheetHeader>, <SheetFooter>
Layout containers padded p-4. Header stacks title and description; footer pushes to the bottom (mt-auto) with gap-2.
<SheetTitle>, <SheetDescription>
Map to Radix Dialog.Title and Dialog.Description. Both are required by Radix; render with className="sr-only" if visually hidden.
<SheetTrigger>, <SheetClose>, <SheetOverlay>, <SheetPortal>
Pass-throughs over the Radix primitives with data-slot attributes.
Composition
<Sheet>owns the open/close state.<SheetTrigger asChild>wraps the focusable element that opens it.<SheetContent side="right">mounts via Portal, draws the overlay, slides in from the chosen edge.- Header carries title and description; body holds the main content; footer pins primary actions at the bottom.
- Dismissal: click overlay, press
Esc, click the X (showCloseButton), or callSheetClose.
Variations
Sides
SheetContent slides in from any edge via the side prop (top, right, bottom, left). Each trigger below opens the sheet from a different edge.
'use client';import { Button } from '@gremorie/rx-forms';import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger,} from '@gremorie/rx-overlays';const sides = ['top', 'right', 'bottom', 'left'] as const;export function SheetSidesPreview() { return ( <div className="flex flex-wrap gap-2"> {sides.map((side) => ( <Sheet key={side}> <SheetTrigger asChild> <Button variant="outline" className="capitalize"> {side} </Button> </SheetTrigger> <SheetContent side={side}> <SheetHeader> <SheetTitle className="capitalize">{side} sheet</SheetTitle> <SheetDescription> This sheet docks against the {side} edge and slides in from there. </SheetDescription> </SheetHeader> </SheetContent> </Sheet> ))} </div> );}Right filter panel
The canonical desktop pattern. Filter form pinned, scrollable body, apply/reset in the footer.
<Sheet>
<SheetTrigger asChild>
<Button variant="outline">Filters</Button>
</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<SheetTitle>Filters</SheetTitle>
</SheetHeader>
<div className="flex-1 overflow-auto px-4">{/* filter form */}</div>
<SheetFooter>
<Button variant="outline">Reset</Button>
<Button>Apply</Button>
</SheetFooter>
</SheetContent>
</Sheet>Left navigation drawer
Pair with a hamburger trigger on mobile for primary navigation.
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" aria-label="Open menu">
<MenuIcon />
</Button>
</SheetTrigger>
<SheetContent side="left">
<SheetHeader>
<SheetTitle>Navigation</SheetTitle>
</SheetHeader>
<nav className="px-4">{/* nav links */}</nav>
</SheetContent>
</Sheet>Bottom notification panel
Use side="bottom" for transient panels that don't deserve a centered modal (system status, recent activity).
<SheetContent side="bottom">
<SheetHeader>
<SheetTitle>Recent activity</SheetTitle>
</SheetHeader>
{/* activity feed */}
</SheetContent>Accessibility
- Role:
role="dialog"witharia-modal="true"(defaultmodalprop). - Keyboard:
Esccloses;Tabcycles focus within the content; focus is trapped while open. - Focus management: focus moves to the first focusable element on open and returns to the trigger on close.
- Title:
SheetTitleis mandatory; without it Radix logs a warning. Usesr-onlyif you need to hide it visually. - Description: links to content via
aria-describedbyautomatically. - Reduced motion: slide animations honor
prefers-reduced-motionvia the underlying Tailwind animate utilities.
Related
- Drawer - vaul-based bottom sheet with drag-to-dismiss for mobile.
- Dialog - centered modal for focused decisions.
- Popover - inline anchored overlay for small contextual UI.
- Navigation Menu - top-level navigation that doesn't overlay.