Enhances the Dialog component to display supporting content for the main interface.
@radix-ui/react-dialog
@lucide/react1'use client'
2
3import { Button } from '@/components/ui/button'
4import { Input } from '@/components/ui/input'
5import { Label } from '@/components/ui/label'
6import {
7 Select,
8 SelectContent,
9 SelectItem,
10 SelectTrigger,
11 SelectValue,
12} from '@/components/ui/select'
13import {
14 Sheet,
15 SheetClose,
16 SheetContent,
17 SheetDescription,
18 SheetFooter,
19 SheetHeader,
20 SheetTitle,
21 SheetTrigger,
22} from '@/components/ui/sheet'
23import { Textarea } from '@/components/ui/textarea'
24
25export function AddTaskSheet() {
26 return (
27 <Sheet>
28 <SheetTrigger asChild>
29 <Button variant="outline">Add Task</Button>
30 </SheetTrigger>
31 <SheetContent>
32 <SheetHeader>
33 <SheetTitle>New Task</SheetTitle>
34 <SheetDescription>
35 Fill out the details for your new task and click save
36 when done.
37 </SheetDescription>
38 </SheetHeader>
39 <div className="grid flex-1 auto-rows-min gap-6 px-4">
40 <div className="grid gap-3">
41 <Label htmlFor="task-title">Title</Label>
42 <Input id="task-title" placeholder="Enter task title" />
43 </div>
44 <div className="grid gap-3">
45 <Label htmlFor="task-desc">Description</Label>
46 <Textarea
47 id="task-desc"
48 placeholder="Enter task description"
49 />
50 </div>
51 <div className="grid gap-3">
52 <Label htmlFor="task-date">Assignee</Label>
53 <Select>
54 <SelectTrigger className="w-full">
55 <SelectValue placeholder="Select Assignee" />
56 </SelectTrigger>
57 <SelectContent>
58 <SelectItem value="amelia-nguyen">
59 Amelia Nguyen
60 </SelectItem>
61 <SelectItem value="liam-roberts">
62 Liam Roberts
63 </SelectItem>
64 <SelectItem value="sofia-morales">
65 Sofia Morales
66 </SelectItem>
67 <SelectItem value="marcus-lee">
68 Marcus Lee
69 </SelectItem>
70 <SelectItem value="nora-kim">
71 Nora Kim
72 </SelectItem>
73 <SelectItem value="lucas-martin">
74 Lucas Martin
75 </SelectItem>
76 </SelectContent>
77 </Select>
78 </div>
79 </div>
80 <SheetFooter>
81 <Button type="submit">Save Task</Button>
82 <SheetClose asChild>
83 <Button variant="outline">Cancel</Button>
84 </SheetClose>
85 </SheetFooter>
86 </SheetContent>
87 </Sheet>
88 )
89}
90
Install the following dependencies:
Specify the side property on <SheetContent />
to control from which edge of the screen the sheet slides in. Accepted values are top
, right
, bottom
, or left
.
1'use client'
2
3import * as React from 'react'
4
5import { Button } from '@/components/ui/button'
6import { Input } from '@/components/ui/input'
7import { Label } from '@/components/ui/label'
8import {
9 Sheet,
10 SheetClose,
11 SheetContent,
12 SheetDescription,
13 SheetFooter,
14 SheetHeader,
15 SheetTitle,
16 SheetTrigger,
17} from '@/components/ui/sheet'
18import { Textarea } from '@/components/ui/textarea'
19
20export function SheetSideDemo() {
21 return (
22 <div className="flex flex-col gap-6">
23 <Sheet>
24 <SheetTrigger asChild>
25 <Button>Open Right Sheet</Button>
26 </SheetTrigger>
27 <SheetContent side="right" className="w-96">
28 <SheetHeader>
29 <SheetTitle>Edit Profile</SheetTitle>
30 <SheetDescription>
31 Update your profile information below.
32 </SheetDescription>
33 </SheetHeader>
34 <div className="grid gap-4 px-4 py-2">
35 <div className="grid gap-1">
36 <Label htmlFor="name">Name</Label>
37 <Input id="name" defaultValue="rafael costa" />
38 </div>
39 <div className="grid gap-1">
40 <Label htmlFor="username">Username</Label>
41 <Input id="username" defaultValue="@rafaelcosta" />
42 </div>
43 <div className="grid gap-1">
44 <Label htmlFor="bio">Bio</Label>
45 <Textarea
46 id="bio"
47 placeholder="Tell us about yourself..."
48 />
49 </div>
50 </div>
51 <SheetClose asChild>
52 <Button variant="outline" className="m-4">
53 Save
54 </Button>
55 </SheetClose>
56 </SheetContent>
57 </Sheet>
58
59 <Sheet>
60 <SheetTrigger asChild>
61 <Button>Open Left Sheet</Button>
62 </SheetTrigger>
63 <SheetContent side="left" className="w-80">
64 <SheetHeader>
65 <SheetTitle>Notifications</SheetTitle>
66 <SheetDescription>
67 Recent activity and alerts.
68 </SheetDescription>
69 </SheetHeader>
70 <ul className="space-y-2 px-4 py-2">
71 <li className="rounded border p-2">
72 New comment on your post
73 </li>
74 <li className="rounded border p-2">
75 New follower: Jane
76 </li>
77 <li className="rounded border p-2">
78 Project deadline approaching
79 </li>
80 </ul>
81 <SheetClose asChild>
82 <Button variant="outline" className="m-4">
83 Close
84 </Button>
85 </SheetClose>
86 </SheetContent>
87 </Sheet>
88
89 <Sheet>
90 <SheetTrigger asChild>
91 <Button>Open Top Sheet</Button>
92 </SheetTrigger>
93 <SheetContent
94 side="top"
95 className="flex h-84 flex-col justify-between"
96 >
97 <SheetHeader>
98 <SheetTitle>Quick Feedback</SheetTitle>
99 <SheetDescription>
100 Send us your quick feedback.
101 </SheetDescription>
102 </SheetHeader>
103
104 <div className="grid gap-3 px-4">
105 <Label htmlFor="feedback">Feedback</Label>
106 <Textarea
107 id="feedback"
108 placeholder="Type your feedback..."
109 />
110 </div>
111
112 <SheetFooter className="flex justify-end gap-2 px-4 py-2">
113 <Button type="submit">Send</Button>
114 <SheetClose asChild>
115 <Button variant="outline">Cancel</Button>
116 </SheetClose>
117 </SheetFooter>
118 </SheetContent>
119 </Sheet>
120
121 <Sheet>
122 <SheetTrigger asChild>
123 <Button>Open Bottom Sheet</Button>
124 </SheetTrigger>
125 <SheetContent side="bottom" className="h-84">
126 <SheetHeader>
127 <SheetTitle>Today's Tasks</SheetTitle>
128 <SheetDescription>
129 Check your tasks for today.
130 </SheetDescription>
131 </SheetHeader>
132 <ul className="space-y-2 px-4 py-2">
133 <li className="rounded border p-2">
134 Meeting with team at 10 AM
135 </li>
136 <li className="rounded border p-2">
137 Finish project report
138 </li>
139 <li className="rounded border p-2">
140 Review pull requests
141 </li>
142 </ul>
143 <SheetClose asChild>
144 <Button variant="outline" className="m-4">
145 Close
146 </Button>
147 </SheetClose>
148 </SheetContent>
149 </Sheet>
150 </div>
151 )
152}
153
Use the <SheetTrigger />
component to define how the sheet is opened.
It can wrap various elements such as buttons, icons, links, or even custom components, providing flexibility in user interactions.
1'use client'
2
3import * as React from 'react'
4import { Bell } from 'lucide-react'
5
6import { Button } from '@/components/ui/button'
7import { Input } from '@/components/ui/input'
8import { Label } from '@/components/ui/label'
9import {
10 Sheet,
11 SheetClose,
12 SheetContent,
13 SheetDescription,
14 SheetFooter,
15 SheetHeader,
16 SheetTitle,
17 SheetTrigger,
18} from '@/components/ui/sheet'
19import { Textarea } from '@/components/ui/textarea'
20
21export function SheetContentDemo() {
22 const notifications = [
23 {
24 id: 1,
25 title: 'New message',
26 desc: 'You have a new message from Sarah',
27 time: '5m ago',
28 },
29 {
30 id: 2,
31 title: 'Update available',
32 desc: 'Version 2.0 is now available',
33 time: '1h ago',
34 },
35 {
36 id: 3,
37 title: 'Task completed',
38 desc: 'Your export has finished',
39 time: '3h ago',
40 },
41 ]
42
43 return (
44 <div className="flex flex-col gap-4 p-8">
45 <Sheet>
46 <SheetTrigger asChild>
47 <Button variant="outline">Button Sheet</Button>
48 </SheetTrigger>
49 <SheetContent side="right" className="w-80 sm:w-96">
50 <SheetHeader>
51 <SheetTitle>Edit Profile</SheetTitle>
52 <SheetDescription>
53 Make changes to your profile here. Click save when
54 you're done.
55 </SheetDescription>
56 </SheetHeader>
57 <div className="flex flex-col gap-4 px-4 py-4">
58 <div className="flex flex-col gap-2">
59 <Label
60 htmlFor="name"
61 className="text-sm font-medium"
62 >
63 Name
64 </Label>
65 <Input
66 id="name"
67 defaultValue="rafael costa"
68 className="rounded-md border border-gray-300 px-3 py-2 text-sm"
69 />
70 </div>
71 <div className="flex flex-col gap-2">
72 <Label
73 htmlFor="email"
74 className="text-sm font-medium"
75 >
76 Email
77 </Label>
78 <Input
79 id="email"
80 type="email"
81 defaultValue="rafael.costa@example.com"
82 className="rounded-md border border-gray-300 px-3 py-2 text-sm"
83 />
84 </div>
85 <div className="flex flex-col gap-2">
86 <Label
87 htmlFor="bio"
88 className="text-sm font-medium"
89 >
90 Bio
91 </Label>
92 <Textarea
93 id="bio"
94 defaultValue="I'm a software developer passionate about building great products."
95 className="rounded-md border border-gray-300 px-3 py-2 text-sm"
96 rows={4}
97 />
98 </div>
99 </div>
100 <SheetFooter>
101 <SheetClose asChild>
102 <Button variant="outline">Cancel</Button>
103 </SheetClose>
104 <Button>Save Changes</Button>
105 </SheetFooter>
106 </SheetContent>
107 </Sheet>
108
109 <Sheet>
110 <SheetTrigger asChild>
111 <Button variant="outline">
112 <Bell className="mr-2 h-4 w-4" />
113 Icon Sheet
114 </Button>
115 </SheetTrigger>
116 <SheetContent side="right" className="w-80 sm:w-96">
117 <SheetHeader>
118 <SheetTitle>Notifications</SheetTitle>
119 <SheetDescription>
120 You have {notifications.length} unread
121 notifications.
122 </SheetDescription>
123 </SheetHeader>
124 <div className="flex flex-col gap-3 px-4 py-4">
125 {notifications.map((notif) => (
126 <div
127 key={notif.id}
128 className="flex items-start gap-3 rounded-lg border p-3 hover:bg-gray-50"
129 >
130 <div className="flex-1">
131 <p className="text-sm font-medium">
132 {notif.title}
133 </p>
134 <p className="text-sm text-gray-600">
135 {notif.desc}
136 </p>
137 <p className="text-gray mt-1 text-xs">
138 {notif.time}
139 </p>
140 </div>
141 </div>
142 ))}
143 {notifications.length === 0 && (
144 <div className="py-8 text-center text-gray-500">
145 No notifications
146 </div>
147 )}
148 </div>
149 <SheetFooter>
150 <Button variant="outline" className="w-full">
151 Clear All
152 </Button>
153 </SheetFooter>
154 </SheetContent>
155 </Sheet>
156
157 <Sheet>
158 <SheetTrigger asChild>
159 <span className="cursor-pointer text-blue-600 underline">
160 Link Sheet
161 </span>
162 </SheetTrigger>
163 <SheetContent side="left" className="w-64">
164 <SheetHeader>
165 <SheetTitle>Menu</SheetTitle>
166 <SheetDescription>
167 Navigate through the application
168 </SheetDescription>
169 </SheetHeader>
170 <nav className="flex flex-col gap-2 py-4">
171 <a
172 href="#"
173 className="rounded-md px-3 py-2 text-sm hover:bg-gray-100"
174 >
175 Dashboard
176 </a>
177 <a
178 href="#"
179 className="rounded-md px-3 py-2 text-sm hover:bg-gray-100"
180 >
181 Projects
182 </a>
183 <a
184 href="#"
185 className="rounded-md px-3 py-2 text-sm hover:bg-gray-100"
186 >
187 Team
188 </a>
189 <a
190 href="#"
191 className="rounded-md px-3 py-2 text-sm hover:bg-gray-100"
192 >
193 Calendar
194 </a>
195 <a
196 href="#"
197 className="rounded-md px-3 py-2 text-sm hover:bg-gray-100"
198 >
199 Documents
200 </a>
201 <hr className="my-2" />
202 <a
203 href="#"
204 className="rounded-md px-3 py-2 text-sm hover:bg-gray-100"
205 >
206 Settings
207 </a>
208 <a
209 href="#"
210 className="rounded-md px-3 py-2 text-sm hover:bg-gray-100"
211 >
212 Help & Support
213 </a>
214 </nav>
215 </SheetContent>
216 </Sheet>
217 </div>
218 )
219}
220
You can open a sheet from within another sheet to handle multi-step workflows or drill-down navigation. This pattern is great for flows like nested settings, detail editing, or multi-step forms.
1'use client'
2
3import * as React from 'react'
4
5import { Button } from '@/components/ui/button'
6import { Input } from '@/components/ui/input'
7import { Label } from '@/components/ui/label'
8import {
9 Select,
10 SelectContent,
11 SelectItem,
12 SelectTrigger,
13 SelectValue,
14} from '@/components/ui/select'
15import {
16 Sheet,
17 SheetClose,
18 SheetContent,
19 SheetDescription,
20 SheetFooter,
21 SheetHeader,
22 SheetTitle,
23 SheetTrigger,
24} from '@/components/ui/sheet'
25
26export function NestedSheetDemo() {
27 return (
28 <Sheet>
29 <SheetTrigger asChild>
30 <Button>Open Main Sheet</Button>
31 </SheetTrigger>
32 <SheetContent side="right" className="w-96">
33 <SheetHeader>
34 <SheetTitle>Account Settings</SheetTitle>
35 <SheetDescription>
36 Manage your basic profile and preferences.
37 </SheetDescription>
38 </SheetHeader>
39
40 <div className="grid gap-4 px-4 py-4">
41 <div className="grid gap-2">
42 <Label htmlFor="name">Name</Label>
43 <Input id="name" placeholder="Enter your name" />
44 </div>
45
46 <div className="grid gap-2">
47 <Label htmlFor="email">Email</Label>
48 <Input id="email" placeholder="you@example.com" />
49 </div>
50
51 <Sheet>
52 <SheetTrigger asChild>
53 <Button>Advanced Settings</Button>
54 </SheetTrigger>
55 <SheetContent side="right" className="w-80">
56 <SheetHeader>
57 <SheetTitle>Advanced Settings</SheetTitle>
58 <SheetDescription>
59 Manage deeper configuration options.
60 </SheetDescription>
61 </SheetHeader>
62
63 <div className="grid gap-2 px-4 py-4">
64 <Label htmlFor="api">API Key</Label>
65 <Input
66 id="api"
67 placeholder="Enter your API key"
68 />
69 <Label htmlFor="mode">Mode</Label>
70 <Select>
71 <SelectTrigger className="w-full">
72 <SelectValue placeholder="Select Mode" />
73 </SelectTrigger>
74 <SelectContent>
75 <SelectItem value="production">
76 Production
77 </SelectItem>
78 <SelectItem value="development">
79 Development
80 </SelectItem>
81 </SelectContent>
82 </Select>
83 </div>
84
85 <SheetFooter className="flex justify-end gap-2 px-4 py-2">
86 <SheetClose asChild>
87 <Button variant="outline">Back</Button>
88 </SheetClose>
89 <SheetClose asChild>
90 <Button>Save</Button>
91 </SheetClose>
92 </SheetFooter>
93 </SheetContent>
94 </Sheet>
95 </div>
96
97 <SheetFooter className="flex justify-end gap-2 px-4 py-2">
98 <SheetClose asChild>
99 <Button variant="outline">Cancel</Button>
100 </SheetClose>
101 <Button type="submit">Save Changes</Button>
102 </SheetFooter>
103 </SheetContent>
104 </Sheet>
105 )
106}
107
Prop | Type | Default |
---|---|---|
open | boolean | - |
onOpenChange | (open: boolean) => void | - |
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Prop | Type | Default |
---|---|---|
side | top ,right ,bottom ,left | right |
children | (open: boolean) => void | - |
Prop | Type | Default |
---|---|---|
asChild | boolean | false |