Sheet
A Sheet shows users a panel that slides over the page from one side of the screen.
When to Use
- to edit a record while the page that it belongs to stays in view, such as “Edit client”
- for a form with more fields than fit in a Dialog, as a side Sheet is as tall as the screen
- for navigation on a narrow screen, as the Sidebar does below 768px
When Not to Use
- for a short form in the center of the screen (use a Dialog)
- for a panel that users swipe away, or one that rests at set heights (use a Drawer)
- to confirm an action that can’t be undone (use an Alert Dialog)
See Dialog for a comparison of the Dialog, the Alert Dialog, the Sheet, and the Drawer.
Anatomy
| Element | Usage |
|---|---|
| Overlay | Required |
| Close button | Shown by default |
| Popup | Required |
| Title* | Required |
| Description | Optional |
| Footer | Optional |
* The title is the Sheet’s accessible name. If the design shows no title, visually hide it and keep it in the markup.
SheetContent renders the portal, the overlay, and the close button, so you don’t need to add them. SheetHeader and SheetFooter have 16px of padding and the popup has none, so add your own padding to the content between them.
The footer is positioned at the bottom edge, and its Buttons are stacked in the order in which they are written. Write the main action first.
Behavior
A Sheet is Base UI’s Dialog fixed to one side of the screen. It is modal, and it opens, closes, and moves focus as a Dialog does.
Position and Size
To choose the edge, set side on SheetContent.
| Side | Position | Size |
|---|---|---|
right, left | That edge, from the top to the bottom | 384px wide from 640px, and 75% of the screen below 640px |
top, bottom | That edge, across the screen | As tall as its content |
If floating is set on SheetContent, the Sheet is inset from the edges of the screen. See Layout for the widths of the other overlays.
side is physical: right is the right edge in both directions. If you want the Sheet at the end edge of a right-to-left layout, pass side="left". See Right-to-Left for how to read the direction.
Overflow
If the content is taller than the Sheet, the Sheet scrolls. To keep the footer in view, see Scroll Long Content.
Safe Areas
When a Sheet touches the top or the bottom of the screen, it adds the safe-area inset of a phone to its padding. The insets apply only if the page sets viewport-fit=cover.
Content
For the title, the description, and the actions of a Sheet, follow the rules for a Dialog.
The label of the close button is labels.sheet.close, which is “Close” by default. To translate it, use the Summit Provider.
Accessibility
A Sheet has the role, the keys, and the focus handling of a Dialog. The close button is last in the popup’s markup, so users reach it with Tab after the footer.
A Sheet needs a SheetTitle so that screen readers can announce what it is for, as WCAG 2.2 SC 4.1.2 Name, Role, Value requires. If
the design shows no title, add sr-only to its SheetHeader to visually hide it, as the Sidebar does.
If showCloseButton is false, keep a SheetClose in the popup. See Dialog for the reason.
Installation
npx shadcn@latest add @summit/sheetThe CLI also adds @summit/button and @summit/summit-provider.
Usage
import { Button } from '@/components/ui/button';
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet';
<Sheet>
<SheetTrigger render={<Button variant="outline" />}>Edit client</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Edit client</SheetTitle>
<SheetDescription>Changes apply to new invoices only.</SheetDescription>
</SheetHeader>
<SheetFooter>
<SheetClose render={<Button />}>Save</SheetClose>
<SheetClose render={<Button variant="outline" />}>Cancel</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>;Choose the Side
To choose the edge, set side to right, left, top, or bottom. To inset the Sheet from the edges of the screen, set floating.
<SheetContent side="left" floating>
<SheetTitle>Filters</SheetTitle>
</SheetContent>Scroll Long Content
To scroll long content, add flex-1 and overflow-y-auto to the content between the header and the footer. The footer then stays at the bottom of the Sheet.
<SheetContent>
<SheetHeader>
<SheetTitle>Edit client</SheetTitle>
</SheetHeader>
<div className="flex-1 overflow-y-auto px-4">{fields}</div>
<SheetFooter>
<SheetClose render={<Button />}>Save</SheetClose>
</SheetFooter>
</SheetContent>Hide the Close Button
To remove the close button in the corner, set showCloseButton={false} on SheetContent.
<SheetContent showCloseButton={false}>
<SheetTitle>Edit client</SheetTitle>
<SheetFooter>
<SheetClose render={<Button variant="outline" />}>Close</SheetClose>
</SheetFooter>
</SheetContent>API Reference
The parts accept the props of their matching parts in Base UI’s Dialog, where SheetContent is Dialog.Popup. SheetHeader and SheetFooter accept the props of a div. See the Base UI Dialog documentation for open, onOpenChange, modal, initialFocus, and finalFocus.
SheetContent
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'right' | 'bottom' | 'left' | 'right' | The edge the Sheet is fixed to |
floating | boolean | false | Insets the Sheet from the edges of the screen and rounds it |
showCloseButton | boolean | true | Shows the close button in the top corner |