Edit profile
Make changes to your profile here. Click save when you're done.
---
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
---
<Sheet>
<SheetTrigger variant="outline">Open</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Edit profile</SheetTitle>
<SheetDescription>
Make changes to your profile here. Click save when you're done.
</SheetDescription>
</SheetHeader>
<div class="grid flex-1 auto-rows-min gap-6 px-4">
<div class="grid gap-3">
<Label for="sheet-demo-name">Name</Label>
<Input id="sheet-demo-name" value="Pedro Duarte" />
</div>
<div class="grid gap-3">
<Label for="sheet-demo-username">Username</Label>
<Input id="sheet-demo-username" value="@peduarte" />
</div>
</div>
<SheetFooter>
<Button type="submit">Save changes</Button>
<SheetClose variant="outline">Close</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>Installation
npx shadcn@latest add @fulldev/sheet
Usage
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
<Sheet>
<SheetTrigger variant="outline">Open</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Are you absolutely sure?</SheetTitle>
<SheetDescription>This action cannot be undone.</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
SheetTrigger and SheetClose render a Button and take its variant and
size props. The sheet uses the Data Slot dialog: it traps focus, closes on
Escape and outside click, and locks page scroll while open.
Composition
Sheet
├── SheetTrigger
└── SheetContent
├── SheetHeader
│ ├── SheetTitle
│ └── SheetDescription
└── SheetFooter
Side
Use the side prop on SheetContent to set the edge of the screen where the
sheet appears. Values are top, right, bottom, or left.
Edit profile
Make changes to your profile here. Click save when you're done.
Edit profile
Make changes to your profile here. Click save when you're done.
Edit profile
Make changes to your profile here. Click save when you're done.
Edit profile
Make changes to your profile here. Click save when you're done.
---
import { Button } from "@/components/ui/button"
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
const SHEET_SIDES = ["top", "right", "bottom", "left"] as const
---
<div class="flex flex-wrap gap-2">
{SHEET_SIDES.map((side) => (
<Sheet>
<SheetTrigger variant="outline" class="capitalize">
{side}
</SheetTrigger>
<SheetContent
side={side}
class="data-[side=bottom]:max-h-[50vh] data-[side=top]:max-h-[50vh]"
>
<SheetHeader>
<SheetTitle>Edit profile</SheetTitle>
<SheetDescription>
Make changes to your profile here. Click save when you're done.
</SheetDescription>
</SheetHeader>
<div class="no-scrollbar overflow-y-auto px-4">
{Array.from({ length: 10 }).map(() => (
<p class="mb-2 leading-relaxed">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
))}
</div>
<SheetFooter>
<Button type="submit">Save changes</Button>
<SheetClose variant="outline">Cancel</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
))}
</div>No Close Button
Use showCloseButton={false} on SheetContent to hide the close button.
No Close Button
This sheet doesn't have a close button in the top-right corner. Click outside to close.
---
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
---
<Sheet>
<SheetTrigger variant="outline">Open Sheet</SheetTrigger>
<SheetContent showCloseButton={false}>
<SheetHeader>
<SheetTitle>No Close Button</SheetTitle>
<SheetDescription>
This sheet doesn't have a close button in the top-right corner.
Click outside to close.
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>RTL
تعديل الملف الشخصي
قم بإجراء تغييرات على ملفك الشخصي هنا. انقر حفظ عند الانتهاء.
---
import { Button } from "@/components/ui/button"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
const translations = {
en: {
dir: "ltr",
values: {
open: "Open",
editProfile: "Edit profile",
description:
"Make changes to your profile here. Click save when you're done.",
name: "Name",
username: "Username",
save: "Save changes",
close: "Close",
},
},
ar: {
dir: "rtl",
values: {
open: "فتح",
editProfile: "تعديل الملف الشخصي",
description:
"قم بإجراء تغييرات على ملفك الشخصي هنا. انقر حفظ عند الانتهاء.",
name: "الاسم",
username: "اسم المستخدم",
save: "حفظ التغييرات",
close: "إغلاق",
},
},
he: {
dir: "rtl",
values: {
open: "פתח",
editProfile: "עריכת פרופיל",
description: "בצע שינויים בפרופיל שלך כאן. לחץ שמור כשתסיים.",
name: "שם",
username: "שם משתמש",
save: "שמור שינויים",
close: "סגור",
},
},
}
const language = "ar"
const { dir, values: t } = translations[language]
---
<Sheet>
<SheetTrigger variant="outline">{t.open}</SheetTrigger>
<SheetContent
dir={dir}
side={dir === "rtl" ? "left" : "right"}
data-lang={dir === "rtl" ? language : undefined}
>
<SheetHeader>
<SheetTitle>{t.editProfile}</SheetTitle>
<SheetDescription>{t.description}</SheetDescription>
</SheetHeader>
<FieldGroup class="px-4">
<Field>
<FieldLabel for="sheet-rtl-name">{t.name}</FieldLabel>
<Input id="sheet-rtl-name" value="Pedro Duarte" />
</Field>
<Field>
<FieldLabel for="sheet-rtl-username">{t.username}</FieldLabel>
<Input id="sheet-rtl-username" value="peduarte" />
</Field>
</FieldGroup>
<SheetFooter>
<Button type="submit">{t.save}</Button>
<SheetClose variant="outline">{t.close}</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>Responsive activation
Pass a media query to Sheet to import and initialize its controller only
while that query matches. Leaving the query destroys the controller and releases
its portals and scroll lock. Returning initializes it again. A trigger click
during the first download is performed once loading finishes, provided the query
still matches.
The default has no breakpoint restriction. Keep the query and CSS visibility in
the owning header block or site. Header blocks use fold="lg" by default and
accept fold="xl"; that choice controls both visibility and activation.
API Reference
Source: src/components/ui/sheet
Sheet
| Prop | Type | Default |
|---|---|---|
defaultOpen | boolean | false |
closeOnClickOutside | boolean | true |
closeOnEscape | boolean | true |
lockScroll | boolean | true |
SheetContent
| Prop | Type | Default |
|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" |
showCloseButton | boolean | true |
See the Data Slot dialog docs for events and programmatic control.