Sheet
Extends the Dialog component to display content that complements the main content of the screen. Perfect for sidebars, forms, and secondary content in React applications with Next.js and TypeScript.
Ever notice how the best mobile apps have those panels that slide in from the edges? That's what sheets do - they're like sidebars but way more flexible. Need a settings panel that slides in from the right? A notification bar from the top? A mobile-style bottom sheet? This component handles all of that.
Quick profile editor
Clean form in a side panel:
Built on Radix UI Dialog with focus management and proper ARIA semantics. This free open source React component handles the overlay, positioning, and animations while you focus on what goes inside.
npx shadcn@latest add sheet
Why sheets beat regular modals
Sheets feel more natural than popup modals:
- Edge positioning - Slides in from top, right, bottom, or left
- Less intrusive - Doesn't cover the whole screen like modals
- Better mobile UX - Native app feel with smooth animations
- Focus management - Traps focus properly with keyboard navigation
- Flexible sizing - Custom widths and heights that make sense
- Contextual - Keeps main content visible while showing details
Practical sheet patterns
Different sides
Panels that slide from any edge:
Project creation form
Complex form in a wide sheet:
These patterns solve real problems - settings panels that don't interrupt your workflow, forms that need more space than a modal, mobile-friendly action sheets.
Perfect for secondary actions
Works great for anything that complements your main content - user profiles, settings, filters, detailed forms, help panels. The kind of stuff that's important but shouldn't take over the entire screen.
Drops right into Next.js projects. Full TypeScript support. Styled with Tailwind CSS to match the shadcn design system.
Built on Radix UI Dialog
Uses Radix UI Dialog under the hood, which handles the complex stuff:
- Focus trapping - Keyboard navigation stays inside the sheet
- Escape key - Closes automatically when users press escape
- Overlay clicks - Click outside to close (or disable it)
- Screen reader - Proper announcements and aria attributes
- Portal rendering - No z-index conflicts
- Animation ready - Smooth enter/exit transitions
API Reference
Sheet
The root container that manages sheet state.
Prop | Type | Default | Description |
---|---|---|---|
defaultOpen | boolean | false | Default open state for uncontrolled |
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Called when open state changes |
modal | boolean | true | Whether sheet is modal |
SheetTrigger
The button that opens the sheet.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Pass functionality to child element |
Data attributes:
[data-state]
: "open" | "closed"
SheetContent
The sheet panel with content.
Prop | Type | Default | Description |
---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" | Which edge to slide from |
className | string | - | Additional CSS classes |
onEscapeKeyDown | (event: KeyboardEvent) => void | - | Handle escape key press |
onPointerDownOutside | (event: PointerDownOutsideEvent) => void | - | Handle clicks outside |
Data attributes:
[data-state]
: "open" | "closed"[data-side]
: "top" | "right" | "bottom" | "left"
SheetHeader
Container for sheet title and description.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes |
SheetTitle
Accessible title announced to screen readers.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes |
SheetDescription
Optional description for screen readers.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes |
SheetFooter
Container for action buttons.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes |
SheetClose
Button that closes the sheet.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Pass functionality to child element |
Keyboard Navigation
Key | Action |
---|---|
Tab | Move focus to next focusable element |
Shift + Tab | Move focus to previous focusable element |
Escape | Close the sheet |
Side Options
Value | Use Case | Best For |
---|---|---|
right | Settings, details, filters | Desktop sidebars, configuration panels |
left | Navigation, menus | App navigation, drawer menus |
bottom | Actions, quick forms | Mobile interfaces, action sheets |
top | Notifications, alerts | Banners, announcement bars |
Common Patterns
Pattern | Use Case | Implementation |
---|---|---|
Settings panel | User preferences | Right side with form controls |
Navigation drawer | App menu | Left side with navigation links |
Filter sidebar | Search filters | Right side with checkboxes/selects |
Quick actions | Mobile actions | Bottom with button grid |
Notifications | Alerts, announcements | Top with dismissible content |
Design tips for better sheets
Keep these in mind when building sheets:
- Size appropriately - Wide enough for content, not too wide to overwhelm
- Consider mobile - Bottom sheets often work better on small screens
- Keep it contextual - Content should relate to what's on the main screen
- Don't overload - Sheets work best with focused, specific content
- Test keyboard nav - Make sure tab order makes sense
- Handle long content - Add scrolling when content exceeds viewport
- Use proper headers - Title and description help screen readers
Separator
Visually or semantically separates content. Perfect for dividing sections, creating navigation breadcrumbs, or organizing layouts in React applications with Next.js and TypeScript.
Skeleton
Use to show a placeholder while content is loading. Perfect for improving perceived performance in React applications with Next.js, TypeScript, and Tailwind CSS.