aural-ui 2.0.5 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/button/index.tsx +6 -0
- package/dist/components/drawer/Drawer.stories.tsx +1166 -0
- package/dist/components/drawer/index.tsx +205 -0
- package/dist/components/drawer/meta.ts +64 -0
- package/dist/components/tabs/Tabs.stories.tsx +179 -2
- package/dist/components/tabs/index.tsx +70 -22
- package/dist/icons/index.ts +1 -0
- package/dist/icons/star-icon/StarIcon.stories.tsx +963 -0
- package/dist/icons/star-icon/index.tsx +22 -0
- package/dist/icons/star-icon/meta.ts +8 -0
- package/dist/index.js +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,1166 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React, { useState } from "react"
|
|
3
|
+
import { Button } from "@components/button"
|
|
4
|
+
import { Checkbox } from "@components/checkbox"
|
|
5
|
+
import Input from "@components/input"
|
|
6
|
+
import { Label } from "@components/label"
|
|
7
|
+
import {
|
|
8
|
+
Select,
|
|
9
|
+
SelectContent,
|
|
10
|
+
SelectItem,
|
|
11
|
+
SelectTrigger,
|
|
12
|
+
SelectValue,
|
|
13
|
+
} from "@components/select"
|
|
14
|
+
import Textarea from "@components/textarea"
|
|
15
|
+
import { CrossIcon } from "@icons/cross-icon"
|
|
16
|
+
import { EditBigIcon } from "@icons/edit-big-icon"
|
|
17
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
Drawer,
|
|
21
|
+
DrawerClose,
|
|
22
|
+
DrawerContent,
|
|
23
|
+
DrawerDescription,
|
|
24
|
+
DrawerFooter,
|
|
25
|
+
DrawerHeader,
|
|
26
|
+
DrawerTitle,
|
|
27
|
+
DrawerTrigger,
|
|
28
|
+
} from "."
|
|
29
|
+
|
|
30
|
+
const meta: Meta<typeof DrawerContent> = {
|
|
31
|
+
title: "Components/UI/Drawer",
|
|
32
|
+
component: Drawer,
|
|
33
|
+
parameters: {
|
|
34
|
+
layout: "centered",
|
|
35
|
+
backgrounds: {
|
|
36
|
+
default: "dark",
|
|
37
|
+
values: [
|
|
38
|
+
{ name: "dark", value: "#0a0a0a" },
|
|
39
|
+
{ name: "light", value: "#ffffff" },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
docs: {
|
|
43
|
+
description: {
|
|
44
|
+
component: `
|
|
45
|
+
# Drawer Component
|
|
46
|
+
|
|
47
|
+
A slide-out drawer component built on Vaul primitives with support for multiple directions, smooth animations, customizable content sections, and enhanced accessibility features.
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
- **Multiple Directions**: Top, bottom, left, and right slide directions
|
|
52
|
+
- **Multiple Variants**: Neutral and gradient styles with custom styling
|
|
53
|
+
- **Custom Overlays**: Configurable opacity, glass effect, and noise texture
|
|
54
|
+
- **Smooth Animations**: Fade in/out animations for overlay and content with customizable duration
|
|
55
|
+
- **Accessible**: Full keyboard navigation, screen reader support, and focus management
|
|
56
|
+
- **Flexible Content**: Header, footer, and body sections with custom styling
|
|
57
|
+
- **Portal Rendering**: Renders outside normal DOM hierarchy for proper layering
|
|
58
|
+
- **Focus Management**: Automatic focus trapping and restoration
|
|
59
|
+
- **Responsive Design**: Adapts to different screen sizes with mobile-first approach
|
|
60
|
+
- **Drag Support**: Built-in drag gestures for intuitive interaction
|
|
61
|
+
- **Nested Support**: Support for nested drawers with proper z-index management
|
|
62
|
+
|
|
63
|
+
## Directions
|
|
64
|
+
|
|
65
|
+
The drawer can slide from different directions using the \`direction\` prop:
|
|
66
|
+
|
|
67
|
+
- **Bottom** (default): Slides up from the bottom - ideal for mobile navigation
|
|
68
|
+
- **Top**: Slides down from the top - useful for notifications or quick actions
|
|
69
|
+
- **Left**: Slides in from the left - perfect for navigation menus
|
|
70
|
+
- **Right**: Slides in from the right - great for settings or detail panels
|
|
71
|
+
|
|
72
|
+
## Usage Examples
|
|
73
|
+
|
|
74
|
+
### Basic Drawer with Direction Configuration
|
|
75
|
+
\`\`\`tsx
|
|
76
|
+
import { Drawer, DrawerContent, DrawerTrigger } from '@/components/drawer'
|
|
77
|
+
|
|
78
|
+
// Bottom drawer (default)
|
|
79
|
+
<Drawer>
|
|
80
|
+
<DrawerTrigger asChild>
|
|
81
|
+
<Button>Open Bottom Drawer</Button>
|
|
82
|
+
</DrawerTrigger>
|
|
83
|
+
<DrawerContent>
|
|
84
|
+
Content slides up from bottom
|
|
85
|
+
</DrawerContent>
|
|
86
|
+
</Drawer>
|
|
87
|
+
|
|
88
|
+
// Top drawer
|
|
89
|
+
<Drawer>
|
|
90
|
+
<DrawerTrigger asChild>
|
|
91
|
+
<Button>Open Top Drawer</Button>
|
|
92
|
+
</DrawerTrigger>
|
|
93
|
+
<DrawerContent>
|
|
94
|
+
Content slides down from top
|
|
95
|
+
</DrawerContent>
|
|
96
|
+
</Drawer>
|
|
97
|
+
|
|
98
|
+
// Left drawer
|
|
99
|
+
<Drawer>
|
|
100
|
+
<DrawerTrigger asChild>
|
|
101
|
+
<Button>Open Left Drawer</Button>
|
|
102
|
+
</DrawerTrigger>
|
|
103
|
+
<DrawerContent>
|
|
104
|
+
Content slides in from left
|
|
105
|
+
</DrawerContent>
|
|
106
|
+
</Drawer>
|
|
107
|
+
|
|
108
|
+
// Right drawer
|
|
109
|
+
<Drawer>
|
|
110
|
+
<DrawerTrigger asChild>
|
|
111
|
+
<Button>Open Right Drawer</Button>
|
|
112
|
+
</DrawerTrigger>
|
|
113
|
+
<DrawerContent>
|
|
114
|
+
Content slides in from right
|
|
115
|
+
</DrawerContent>
|
|
116
|
+
</Drawer>
|
|
117
|
+
|
|
118
|
+
### Drawer with Custom Overlay Effects
|
|
119
|
+
\`\`\`tsx
|
|
120
|
+
<Drawer>
|
|
121
|
+
<DrawerTrigger asChild>
|
|
122
|
+
<Button>Open Drawer with Custom Overlay</Button>
|
|
123
|
+
</DrawerTrigger>
|
|
124
|
+
<DrawerContent
|
|
125
|
+
noise="high"
|
|
126
|
+
opacity="medium"
|
|
127
|
+
glass="low"
|
|
128
|
+
>
|
|
129
|
+
Content with custom overlay effects
|
|
130
|
+
</DrawerContent>
|
|
131
|
+
</Drawer>
|
|
132
|
+
\`\`\`
|
|
133
|
+
|
|
134
|
+
### Overlay Configuration
|
|
135
|
+
|
|
136
|
+
The drawer supports configurable overlay effects through the \`opacity\`, \`glass\`, and \`noise\` props:
|
|
137
|
+
|
|
138
|
+
- **opacity**: Controls background dimming level
|
|
139
|
+
- \`"high"\` - Strong dimming (80%)
|
|
140
|
+
- \`"medium"\` - Balanced dimming (60%) - default
|
|
141
|
+
- \`"low"\` - Subtle dimming (40%)
|
|
142
|
+
- \`"none"\` - No dimming (100% coverage)
|
|
143
|
+
|
|
144
|
+
- **glass**: Controls backdrop blur effect
|
|
145
|
+
- \`"high"\` - Strong blur effect
|
|
146
|
+
- \`"medium"\` - Balanced blur effect
|
|
147
|
+
- \`"low"\` - Subtle blur effect - default
|
|
148
|
+
- \`"none"\` - No blur effect
|
|
149
|
+
|
|
150
|
+
- **noise**: Controls texture overlay
|
|
151
|
+
- \`"high"\` - Strong texture pattern
|
|
152
|
+
- \`"medium"\` - Balanced texture pattern
|
|
153
|
+
- \`"low"\` - Subtle texture pattern - default
|
|
154
|
+
- \`"none"\` - No texture pattern
|
|
155
|
+
|
|
156
|
+
### Usage Examples
|
|
157
|
+
|
|
158
|
+
\`\`\`tsx
|
|
159
|
+
// High opacity with glass effect
|
|
160
|
+
<DrawerContent opacity="high" glass="medium" noise="low">
|
|
161
|
+
Content with strong background dimming
|
|
162
|
+
</DrawerContent>
|
|
163
|
+
|
|
164
|
+
// Subtle overlay with texture
|
|
165
|
+
<DrawerContent opacity="low" glass="none" noise="high">
|
|
166
|
+
Content with subtle dimming and strong texture
|
|
167
|
+
</DrawerContent>
|
|
168
|
+
|
|
169
|
+
// No overlay effects
|
|
170
|
+
<DrawerContent opacity="none" glass="none" noise="none">
|
|
171
|
+
Content without any overlay effects
|
|
172
|
+
</DrawerContent>
|
|
173
|
+
\`\`\`
|
|
174
|
+
\`\`\`
|
|
175
|
+
|
|
176
|
+
### Drawer with Form Elements
|
|
177
|
+
\`\`\`tsx
|
|
178
|
+
<Drawer>
|
|
179
|
+
<DrawerTrigger asChild>
|
|
180
|
+
<Button>Open Form Drawer</Button>
|
|
181
|
+
</DrawerTrigger>
|
|
182
|
+
<DrawerContent>
|
|
183
|
+
<DrawerHeader>
|
|
184
|
+
<DrawerTitle>Contact Form</DrawerTitle>
|
|
185
|
+
<DrawerDescription>Fill out the form below to get in touch.</DrawerDescription>
|
|
186
|
+
</DrawerHeader>
|
|
187
|
+
<div className="space-y-4 p-4">
|
|
188
|
+
<Input placeholder="Name" />
|
|
189
|
+
<Input placeholder="Email" type="email" />
|
|
190
|
+
<Textarea placeholder="Message" rows={4} />
|
|
191
|
+
</div>
|
|
192
|
+
<DrawerFooter>
|
|
193
|
+
<Button>Submit</Button>
|
|
194
|
+
<DrawerClose asChild>
|
|
195
|
+
<Button variant="outline">Cancel</Button>
|
|
196
|
+
</DrawerClose>
|
|
197
|
+
</DrawerFooter>
|
|
198
|
+
</DrawerContent>
|
|
199
|
+
</Drawer>
|
|
200
|
+
\`\`\`
|
|
201
|
+
`,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
argTypes: {
|
|
206
|
+
variant: {
|
|
207
|
+
control: { type: "select" },
|
|
208
|
+
options: ["neutral", "gradient"],
|
|
209
|
+
description: "Drawer variant for different use cases",
|
|
210
|
+
},
|
|
211
|
+
showOverlay: {
|
|
212
|
+
control: { type: "boolean" },
|
|
213
|
+
description: "Whether to show the overlay backdrop",
|
|
214
|
+
},
|
|
215
|
+
showSwipeButton: {
|
|
216
|
+
control: { type: "boolean" },
|
|
217
|
+
description: "Whether to show the swipe indicator button",
|
|
218
|
+
},
|
|
219
|
+
opacity: {
|
|
220
|
+
control: { type: "select" },
|
|
221
|
+
options: ["high", "medium", "low", "none"],
|
|
222
|
+
description: "Overlay opacity level",
|
|
223
|
+
},
|
|
224
|
+
glass: {
|
|
225
|
+
control: { type: "select" },
|
|
226
|
+
options: ["high", "medium", "low", "none"],
|
|
227
|
+
description: "Overlay glass effect level",
|
|
228
|
+
},
|
|
229
|
+
noise: {
|
|
230
|
+
control: { type: "select" },
|
|
231
|
+
options: ["high", "medium", "low", "none"],
|
|
232
|
+
description: "Overlay noise texture level",
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
tags: ["autodocs"],
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export default meta
|
|
239
|
+
type Story = StoryObj<typeof Drawer>
|
|
240
|
+
|
|
241
|
+
// 1. Direction Examples
|
|
242
|
+
export const DirectionExamples: Story = {
|
|
243
|
+
render: () => {
|
|
244
|
+
const DirectionDrawer = ({ direction, title, description }: any) => {
|
|
245
|
+
return (
|
|
246
|
+
<Drawer direction={direction}>
|
|
247
|
+
<DrawerTrigger asChild>
|
|
248
|
+
<Button variant="outline" size="sm">
|
|
249
|
+
{title}
|
|
250
|
+
</Button>
|
|
251
|
+
</DrawerTrigger>
|
|
252
|
+
<DrawerContent>
|
|
253
|
+
<DrawerHeader>
|
|
254
|
+
<DrawerTitle>{title}</DrawerTitle>
|
|
255
|
+
<DrawerDescription>{description}</DrawerDescription>
|
|
256
|
+
</DrawerHeader>
|
|
257
|
+
<div className="p-2 py-4">
|
|
258
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-3">
|
|
259
|
+
<div className="space-y-1 text-xs text-white/60">
|
|
260
|
+
<div>
|
|
261
|
+
Direction: <span className="text-white">{direction}</span>
|
|
262
|
+
</div>
|
|
263
|
+
<div>
|
|
264
|
+
Content:{" "}
|
|
265
|
+
<span className="text-white">Slides from {direction}</span>
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
<DrawerFooter>
|
|
271
|
+
<DrawerClose asChild>
|
|
272
|
+
<Button>Close</Button>
|
|
273
|
+
</DrawerClose>
|
|
274
|
+
</DrawerFooter>
|
|
275
|
+
</DrawerContent>
|
|
276
|
+
</Drawer>
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<div className="space-y-8">
|
|
282
|
+
<div className="text-center">
|
|
283
|
+
<h3 className="mb-2 font-medium text-white">Drawer Directions</h3>
|
|
284
|
+
<p className="text-sm text-white/60">
|
|
285
|
+
Explore different slide directions for various use cases
|
|
286
|
+
</p>
|
|
287
|
+
</div>
|
|
288
|
+
|
|
289
|
+
<div className="space-y-6">
|
|
290
|
+
{/* Bottom Direction */}
|
|
291
|
+
<div className="space-y-4">
|
|
292
|
+
<h4 className="text-sm font-medium text-white/80">
|
|
293
|
+
Bottom Direction (Default)
|
|
294
|
+
</h4>
|
|
295
|
+
<div className="flex flex-wrap gap-2">
|
|
296
|
+
<DirectionDrawer
|
|
297
|
+
direction="bottom"
|
|
298
|
+
title="Bottom Drawer"
|
|
299
|
+
description="Slides up from the bottom - ideal for mobile navigation"
|
|
300
|
+
/>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
|
|
304
|
+
{/* Top Direction */}
|
|
305
|
+
<div className="space-y-4">
|
|
306
|
+
<h4 className="text-sm font-medium text-white/80">Top Direction</h4>
|
|
307
|
+
<div className="flex flex-wrap gap-2">
|
|
308
|
+
<DirectionDrawer
|
|
309
|
+
direction="top"
|
|
310
|
+
title="Top Drawer"
|
|
311
|
+
description="Slides down from the top - useful for notifications"
|
|
312
|
+
/>
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
|
|
316
|
+
{/* Left Direction */}
|
|
317
|
+
<div className="space-y-4">
|
|
318
|
+
<h4 className="text-sm font-medium text-white/80">
|
|
319
|
+
Left Direction
|
|
320
|
+
</h4>
|
|
321
|
+
<div className="flex flex-wrap gap-2">
|
|
322
|
+
<DirectionDrawer
|
|
323
|
+
direction="left"
|
|
324
|
+
title="Left Drawer"
|
|
325
|
+
description="Slides in from the left - perfect for navigation menus"
|
|
326
|
+
/>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
|
|
330
|
+
{/* Right Direction */}
|
|
331
|
+
<div className="space-y-4">
|
|
332
|
+
<h4 className="text-sm font-medium text-white/80">
|
|
333
|
+
Right Direction
|
|
334
|
+
</h4>
|
|
335
|
+
<div className="flex flex-wrap gap-2">
|
|
336
|
+
<DirectionDrawer
|
|
337
|
+
direction="right"
|
|
338
|
+
title="Right Drawer"
|
|
339
|
+
description="Slides in from the right - great for settings panels"
|
|
340
|
+
/>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
)
|
|
346
|
+
},
|
|
347
|
+
parameters: {
|
|
348
|
+
docs: {
|
|
349
|
+
description: {
|
|
350
|
+
story:
|
|
351
|
+
"Comprehensive showcase of all drawer direction options with descriptions of their use cases.",
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// 6. Basic Drawer
|
|
358
|
+
export const Basic: Story = {
|
|
359
|
+
render: () => (
|
|
360
|
+
<Drawer>
|
|
361
|
+
<DrawerTrigger asChild>
|
|
362
|
+
<Button>Open Drawer</Button>
|
|
363
|
+
</DrawerTrigger>
|
|
364
|
+
<DrawerContent>
|
|
365
|
+
<DrawerHeader>
|
|
366
|
+
<DrawerTitle>Basic Drawer</DrawerTitle>
|
|
367
|
+
<DrawerDescription>
|
|
368
|
+
This is a basic drawer example with header, content, and footer.
|
|
369
|
+
</DrawerDescription>
|
|
370
|
+
</DrawerHeader>
|
|
371
|
+
<p className="p-4 text-sm">
|
|
372
|
+
This is the main content area of the drawer. You can put any content
|
|
373
|
+
here.
|
|
374
|
+
</p>
|
|
375
|
+
<DrawerFooter>
|
|
376
|
+
<Button>Save Changes</Button>
|
|
377
|
+
<DrawerClose asChild>
|
|
378
|
+
<Button variant="outline">Cancel</Button>
|
|
379
|
+
</DrawerClose>
|
|
380
|
+
</DrawerFooter>
|
|
381
|
+
</DrawerContent>
|
|
382
|
+
</Drawer>
|
|
383
|
+
),
|
|
384
|
+
parameters: {
|
|
385
|
+
docs: {
|
|
386
|
+
description: {
|
|
387
|
+
story:
|
|
388
|
+
"Basic drawer example demonstrating the fundamental structure with header, content, and footer sections.",
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
}
|
|
393
|
+
// 2. Form Drawer with Select Components
|
|
394
|
+
export const FormDrawer: Story = {
|
|
395
|
+
render: () => {
|
|
396
|
+
const [formData, setFormData] = useState({
|
|
397
|
+
name: "",
|
|
398
|
+
email: "",
|
|
399
|
+
category: "",
|
|
400
|
+
priority: "",
|
|
401
|
+
message: "",
|
|
402
|
+
newsletter: false,
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
406
|
+
e.preventDefault()
|
|
407
|
+
console.log("Form submitted:", formData)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return (
|
|
411
|
+
<Drawer>
|
|
412
|
+
<DrawerTrigger asChild>
|
|
413
|
+
<Button className="gap-2">
|
|
414
|
+
<EditBigIcon className="h-4 w-4" />
|
|
415
|
+
Contact Form
|
|
416
|
+
</Button>
|
|
417
|
+
</DrawerTrigger>
|
|
418
|
+
<DrawerContent>
|
|
419
|
+
<DrawerHeader>
|
|
420
|
+
<DrawerTitle>Contact Form</DrawerTitle>
|
|
421
|
+
<DrawerDescription>
|
|
422
|
+
Fill out the form below to get in touch with us.
|
|
423
|
+
</DrawerDescription>
|
|
424
|
+
</DrawerHeader>
|
|
425
|
+
<form onSubmit={handleSubmit} className="space-y-4 overflow-auto p-4">
|
|
426
|
+
<div className="space-y-2">
|
|
427
|
+
<Label htmlFor="name">Name</Label>
|
|
428
|
+
<Input
|
|
429
|
+
id="name"
|
|
430
|
+
value={formData.name}
|
|
431
|
+
onChange={(e) =>
|
|
432
|
+
setFormData({ ...formData, name: e.target.value })
|
|
433
|
+
}
|
|
434
|
+
placeholder="Enter your name"
|
|
435
|
+
/>
|
|
436
|
+
</div>
|
|
437
|
+
<div className="space-y-2">
|
|
438
|
+
<Label htmlFor="email">Email</Label>
|
|
439
|
+
<Input
|
|
440
|
+
id="email"
|
|
441
|
+
type="email"
|
|
442
|
+
value={formData.email}
|
|
443
|
+
onChange={(e) =>
|
|
444
|
+
setFormData({ ...formData, email: e.target.value })
|
|
445
|
+
}
|
|
446
|
+
placeholder="Enter your email"
|
|
447
|
+
/>
|
|
448
|
+
</div>
|
|
449
|
+
<div className="space-y-2">
|
|
450
|
+
<Label htmlFor="category">Category</Label>
|
|
451
|
+
<Select
|
|
452
|
+
value={formData.category}
|
|
453
|
+
onValueChange={(value) =>
|
|
454
|
+
setFormData({ ...formData, category: value })
|
|
455
|
+
}
|
|
456
|
+
>
|
|
457
|
+
<SelectTrigger>
|
|
458
|
+
<SelectValue placeholder="Select a category" />
|
|
459
|
+
</SelectTrigger>
|
|
460
|
+
<SelectContent>
|
|
461
|
+
<SelectItem value="general">General Inquiry</SelectItem>
|
|
462
|
+
<SelectItem value="support">Technical Support</SelectItem>
|
|
463
|
+
<SelectItem value="sales">Sales Question</SelectItem>
|
|
464
|
+
<SelectItem value="feedback">Feedback</SelectItem>
|
|
465
|
+
</SelectContent>
|
|
466
|
+
</Select>
|
|
467
|
+
</div>
|
|
468
|
+
<div className="space-y-2">
|
|
469
|
+
<Label htmlFor="priority">Priority</Label>
|
|
470
|
+
<Select
|
|
471
|
+
value={formData.priority}
|
|
472
|
+
onValueChange={(value) =>
|
|
473
|
+
setFormData({ ...formData, priority: value })
|
|
474
|
+
}
|
|
475
|
+
>
|
|
476
|
+
<SelectTrigger>
|
|
477
|
+
<SelectValue placeholder="Select priority level" />
|
|
478
|
+
</SelectTrigger>
|
|
479
|
+
<SelectContent>
|
|
480
|
+
<SelectItem value="low">Low</SelectItem>
|
|
481
|
+
<SelectItem value="medium">Medium</SelectItem>
|
|
482
|
+
<SelectItem value="high">High</SelectItem>
|
|
483
|
+
<SelectItem value="urgent">Urgent</SelectItem>
|
|
484
|
+
</SelectContent>
|
|
485
|
+
</Select>
|
|
486
|
+
</div>
|
|
487
|
+
<div className="space-y-2">
|
|
488
|
+
<Label htmlFor="message">Message</Label>
|
|
489
|
+
<Textarea
|
|
490
|
+
id="message"
|
|
491
|
+
value={formData.message}
|
|
492
|
+
onChange={(e) =>
|
|
493
|
+
setFormData({ ...formData, message: e.target.value })
|
|
494
|
+
}
|
|
495
|
+
placeholder="Enter your message"
|
|
496
|
+
rows={4}
|
|
497
|
+
/>
|
|
498
|
+
</div>
|
|
499
|
+
<div className="flex items-center space-x-2">
|
|
500
|
+
<Checkbox
|
|
501
|
+
id="newsletter"
|
|
502
|
+
checked={formData.newsletter}
|
|
503
|
+
onCheckedChange={(checked) =>
|
|
504
|
+
setFormData({ ...formData, newsletter: !!checked })
|
|
505
|
+
}
|
|
506
|
+
/>
|
|
507
|
+
<Label htmlFor="newsletter" className="text-sm">
|
|
508
|
+
Subscribe to newsletter
|
|
509
|
+
</Label>
|
|
510
|
+
</div>
|
|
511
|
+
</form>
|
|
512
|
+
<DrawerFooter>
|
|
513
|
+
<Button
|
|
514
|
+
disabled={!formData.name || !formData.email || !formData.message}
|
|
515
|
+
onClick={handleSubmit}
|
|
516
|
+
>
|
|
517
|
+
Submit
|
|
518
|
+
</Button>
|
|
519
|
+
<DrawerClose asChild>
|
|
520
|
+
<Button variant="outline">Cancel</Button>
|
|
521
|
+
</DrawerClose>
|
|
522
|
+
</DrawerFooter>
|
|
523
|
+
</DrawerContent>
|
|
524
|
+
</Drawer>
|
|
525
|
+
)
|
|
526
|
+
},
|
|
527
|
+
parameters: {
|
|
528
|
+
docs: {
|
|
529
|
+
description: {
|
|
530
|
+
story:
|
|
531
|
+
"Form drawer with select components instead of native select tags, demonstrating proper form handling and validation.",
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// 3. Settings Drawer with Select Components
|
|
538
|
+
export const SettingsDrawer: Story = {
|
|
539
|
+
render: () => {
|
|
540
|
+
const [settings, setSettings] = useState({
|
|
541
|
+
theme: "dark",
|
|
542
|
+
notifications: "important",
|
|
543
|
+
language: "en",
|
|
544
|
+
timezone: "utc",
|
|
545
|
+
})
|
|
546
|
+
|
|
547
|
+
return (
|
|
548
|
+
<Drawer>
|
|
549
|
+
<DrawerTrigger asChild>
|
|
550
|
+
<Button>Open Settings</Button>
|
|
551
|
+
</DrawerTrigger>
|
|
552
|
+
<DrawerContent>
|
|
553
|
+
<DrawerHeader>
|
|
554
|
+
<DrawerTitle>Settings</DrawerTitle>
|
|
555
|
+
<DrawerDescription>
|
|
556
|
+
Configure your application preferences.
|
|
557
|
+
</DrawerDescription>
|
|
558
|
+
</DrawerHeader>
|
|
559
|
+
<div className="space-y-6 overflow-auto p-4">
|
|
560
|
+
<div className="space-y-4">
|
|
561
|
+
<h3 className="text-sm font-medium">Appearance</h3>
|
|
562
|
+
<div className="space-y-2">
|
|
563
|
+
<Label htmlFor="theme">Theme</Label>
|
|
564
|
+
<Select
|
|
565
|
+
value={settings.theme}
|
|
566
|
+
onValueChange={(value) =>
|
|
567
|
+
setSettings({ ...settings, theme: value })
|
|
568
|
+
}
|
|
569
|
+
>
|
|
570
|
+
<SelectTrigger>
|
|
571
|
+
<SelectValue />
|
|
572
|
+
</SelectTrigger>
|
|
573
|
+
<SelectContent>
|
|
574
|
+
<SelectItem value="light">Light</SelectItem>
|
|
575
|
+
<SelectItem value="dark">Dark</SelectItem>
|
|
576
|
+
<SelectItem value="system">System</SelectItem>
|
|
577
|
+
</SelectContent>
|
|
578
|
+
</Select>
|
|
579
|
+
</div>
|
|
580
|
+
</div>
|
|
581
|
+
<div className="space-y-4">
|
|
582
|
+
<h3 className="text-sm font-medium">Notifications</h3>
|
|
583
|
+
<div className="space-y-2">
|
|
584
|
+
<Label htmlFor="notifications">Email Notifications</Label>
|
|
585
|
+
<Select
|
|
586
|
+
value={settings.notifications}
|
|
587
|
+
onValueChange={(value) =>
|
|
588
|
+
setSettings({ ...settings, notifications: value })
|
|
589
|
+
}
|
|
590
|
+
>
|
|
591
|
+
<SelectTrigger>
|
|
592
|
+
<SelectValue />
|
|
593
|
+
</SelectTrigger>
|
|
594
|
+
<SelectContent>
|
|
595
|
+
<SelectItem value="all">All notifications</SelectItem>
|
|
596
|
+
<SelectItem value="important">Important only</SelectItem>
|
|
597
|
+
<SelectItem value="none">None</SelectItem>
|
|
598
|
+
</SelectContent>
|
|
599
|
+
</Select>
|
|
600
|
+
</div>
|
|
601
|
+
</div>
|
|
602
|
+
<div className="space-y-4">
|
|
603
|
+
<h3 className="text-sm font-medium">Regional</h3>
|
|
604
|
+
<div className="space-y-2">
|
|
605
|
+
<Label htmlFor="language">Language</Label>
|
|
606
|
+
<Select
|
|
607
|
+
value={settings.language}
|
|
608
|
+
onValueChange={(value) =>
|
|
609
|
+
setSettings({ ...settings, language: value })
|
|
610
|
+
}
|
|
611
|
+
>
|
|
612
|
+
<SelectTrigger>
|
|
613
|
+
<SelectValue />
|
|
614
|
+
</SelectTrigger>
|
|
615
|
+
<SelectContent>
|
|
616
|
+
<SelectItem value="en">English</SelectItem>
|
|
617
|
+
<SelectItem value="es">Spanish</SelectItem>
|
|
618
|
+
<SelectItem value="fr">French</SelectItem>
|
|
619
|
+
<SelectItem value="de">German</SelectItem>
|
|
620
|
+
</SelectContent>
|
|
621
|
+
</Select>
|
|
622
|
+
</div>
|
|
623
|
+
<div className="space-y-2">
|
|
624
|
+
<Label htmlFor="timezone">Timezone</Label>
|
|
625
|
+
<Select
|
|
626
|
+
value={settings.timezone}
|
|
627
|
+
onValueChange={(value) =>
|
|
628
|
+
setSettings({ ...settings, timezone: value })
|
|
629
|
+
}
|
|
630
|
+
>
|
|
631
|
+
<SelectTrigger>
|
|
632
|
+
<SelectValue />
|
|
633
|
+
</SelectTrigger>
|
|
634
|
+
<SelectContent>
|
|
635
|
+
<SelectItem value="utc">UTC</SelectItem>
|
|
636
|
+
<SelectItem value="est">Eastern Time</SelectItem>
|
|
637
|
+
<SelectItem value="pst">Pacific Time</SelectItem>
|
|
638
|
+
<SelectItem value="gmt">GMT</SelectItem>
|
|
639
|
+
</SelectContent>
|
|
640
|
+
</Select>
|
|
641
|
+
</div>
|
|
642
|
+
</div>
|
|
643
|
+
</div>
|
|
644
|
+
<DrawerFooter>
|
|
645
|
+
<Button onClick={() => console.log("Settings saved:", settings)}>
|
|
646
|
+
Save Settings
|
|
647
|
+
</Button>
|
|
648
|
+
<DrawerClose asChild>
|
|
649
|
+
<Button variant="outline">Cancel</Button>
|
|
650
|
+
</DrawerClose>
|
|
651
|
+
</DrawerFooter>
|
|
652
|
+
</DrawerContent>
|
|
653
|
+
</Drawer>
|
|
654
|
+
)
|
|
655
|
+
},
|
|
656
|
+
parameters: {
|
|
657
|
+
docs: {
|
|
658
|
+
description: {
|
|
659
|
+
story:
|
|
660
|
+
"Settings drawer showcasing select components for configuration options with proper state management.",
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
},
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// 4. Nested Drawers
|
|
667
|
+
export const NestedDrawers: Story = {
|
|
668
|
+
render: () => {
|
|
669
|
+
const [isNestedOpen, setIsNestedOpen] = useState(false)
|
|
670
|
+
|
|
671
|
+
return (
|
|
672
|
+
<Drawer>
|
|
673
|
+
<DrawerTrigger asChild>
|
|
674
|
+
<Button>Open Parent Drawer</Button>
|
|
675
|
+
</DrawerTrigger>
|
|
676
|
+
<DrawerContent>
|
|
677
|
+
<DrawerHeader>
|
|
678
|
+
<DrawerTitle>Parent Drawer</DrawerTitle>
|
|
679
|
+
<DrawerDescription>
|
|
680
|
+
This drawer contains a nested drawer example.
|
|
681
|
+
</DrawerDescription>
|
|
682
|
+
</DrawerHeader>
|
|
683
|
+
<div className="space-y-4 p-4">
|
|
684
|
+
<p className="text-muted-foreground text-sm">
|
|
685
|
+
This is the parent drawer content.
|
|
686
|
+
</p>
|
|
687
|
+
<Drawer open={isNestedOpen} onOpenChange={setIsNestedOpen}>
|
|
688
|
+
<DrawerTrigger asChild>
|
|
689
|
+
<Button variant="outline">Open Nested Drawer</Button>
|
|
690
|
+
</DrawerTrigger>
|
|
691
|
+
<DrawerContent>
|
|
692
|
+
<DrawerHeader>
|
|
693
|
+
<DrawerTitle>Nested Drawer</DrawerTitle>
|
|
694
|
+
<DrawerDescription>
|
|
695
|
+
This is a nested drawer within the parent drawer.
|
|
696
|
+
</DrawerDescription>
|
|
697
|
+
</DrawerHeader>
|
|
698
|
+
<div className="p-4">
|
|
699
|
+
<p className="text-muted-foreground text-sm">
|
|
700
|
+
Nested drawer content goes here.
|
|
701
|
+
</p>
|
|
702
|
+
</div>
|
|
703
|
+
<DrawerFooter>
|
|
704
|
+
<Button onClick={() => setIsNestedOpen(false)}>
|
|
705
|
+
Close Nested
|
|
706
|
+
</Button>
|
|
707
|
+
<DrawerClose asChild>
|
|
708
|
+
<Button variant="outline">Cancel</Button>
|
|
709
|
+
</DrawerClose>
|
|
710
|
+
</DrawerFooter>
|
|
711
|
+
</DrawerContent>
|
|
712
|
+
</Drawer>
|
|
713
|
+
</div>
|
|
714
|
+
<DrawerFooter>
|
|
715
|
+
<Button>Save</Button>
|
|
716
|
+
<DrawerClose asChild>
|
|
717
|
+
<Button variant="outline">Close Parent</Button>
|
|
718
|
+
</DrawerClose>
|
|
719
|
+
</DrawerFooter>
|
|
720
|
+
</DrawerContent>
|
|
721
|
+
</Drawer>
|
|
722
|
+
)
|
|
723
|
+
},
|
|
724
|
+
parameters: {
|
|
725
|
+
docs: {
|
|
726
|
+
description: {
|
|
727
|
+
story:
|
|
728
|
+
"Nested drawer example demonstrating proper modal stacking and z-index management.",
|
|
729
|
+
},
|
|
730
|
+
},
|
|
731
|
+
},
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// 5. Custom Close Button
|
|
735
|
+
export const CustomCloseButton: Story = {
|
|
736
|
+
render: () => (
|
|
737
|
+
<Drawer>
|
|
738
|
+
<DrawerTrigger asChild>
|
|
739
|
+
<Button>Open Drawer with Custom Close</Button>
|
|
740
|
+
</DrawerTrigger>
|
|
741
|
+
<DrawerContent>
|
|
742
|
+
<DrawerHeader>
|
|
743
|
+
<div className="flex items-center justify-between">
|
|
744
|
+
<div className="flex-1 text-center">
|
|
745
|
+
<DrawerTitle>Custom Close Button</DrawerTitle>
|
|
746
|
+
<DrawerDescription>
|
|
747
|
+
This drawer has a custom close button in the header.
|
|
748
|
+
</DrawerDescription>
|
|
749
|
+
</div>
|
|
750
|
+
<DrawerClose asChild>
|
|
751
|
+
<Button variant="text" size="sm" className="ml-4">
|
|
752
|
+
<CrossIcon className="h-4 w-4" />
|
|
753
|
+
</Button>
|
|
754
|
+
</DrawerClose>
|
|
755
|
+
</div>
|
|
756
|
+
</DrawerHeader>
|
|
757
|
+
|
|
758
|
+
<DrawerFooter>
|
|
759
|
+
<Button>Confirm</Button>
|
|
760
|
+
<DrawerClose asChild>
|
|
761
|
+
<Button variant="outline">Cancel</Button>
|
|
762
|
+
</DrawerClose>
|
|
763
|
+
</DrawerFooter>
|
|
764
|
+
</DrawerContent>
|
|
765
|
+
</Drawer>
|
|
766
|
+
),
|
|
767
|
+
parameters: {
|
|
768
|
+
docs: {
|
|
769
|
+
description: {
|
|
770
|
+
story:
|
|
771
|
+
"Drawer with custom close button positioned in the header for enhanced user experience.",
|
|
772
|
+
},
|
|
773
|
+
},
|
|
774
|
+
},
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// 6. Accessibility Example
|
|
778
|
+
export const AccessibilityExample: Story = {
|
|
779
|
+
render: () => {
|
|
780
|
+
return (
|
|
781
|
+
<Drawer>
|
|
782
|
+
<DrawerTrigger asChild>
|
|
783
|
+
<Button>Accessible Drawer Demo</Button>
|
|
784
|
+
</DrawerTrigger>
|
|
785
|
+
<DrawerContent>
|
|
786
|
+
<DrawerHeader>
|
|
787
|
+
<DrawerTitle>Accessibility Features</DrawerTitle>
|
|
788
|
+
<DrawerDescription>
|
|
789
|
+
This drawer demonstrates proper accessibility implementation.
|
|
790
|
+
</DrawerDescription>
|
|
791
|
+
</DrawerHeader>
|
|
792
|
+
|
|
793
|
+
<div className="space-y-4 overflow-auto p-4">
|
|
794
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
795
|
+
<h4 className="mb-2 font-medium text-white">
|
|
796
|
+
Keyboard Navigation
|
|
797
|
+
</h4>
|
|
798
|
+
<ul className="space-y-1 text-sm text-white/80">
|
|
799
|
+
<li>
|
|
800
|
+
• <kbd className="rounded bg-white/10 px-1">Tab</kbd> -
|
|
801
|
+
Navigate between elements
|
|
802
|
+
</li>
|
|
803
|
+
<li>
|
|
804
|
+
• <kbd className="rounded bg-white/10 px-1">Escape</kbd> -
|
|
805
|
+
Close drawer
|
|
806
|
+
</li>
|
|
807
|
+
<li>
|
|
808
|
+
• <kbd className="rounded bg-white/10 px-1">Enter</kbd> -
|
|
809
|
+
Activate buttons
|
|
810
|
+
</li>
|
|
811
|
+
<li>
|
|
812
|
+
• <kbd className="rounded bg-white/10 px-1">Space</kbd> -
|
|
813
|
+
Activate buttons
|
|
814
|
+
</li>
|
|
815
|
+
</ul>
|
|
816
|
+
</div>
|
|
817
|
+
|
|
818
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
819
|
+
<h4 className="mb-2 font-medium text-white">Focus Management</h4>
|
|
820
|
+
<ul className="space-y-1 text-sm text-white/80">
|
|
821
|
+
<li>• Automatic focus trapping within drawer</li>
|
|
822
|
+
<li>• Focus restoration when drawer closes</li>
|
|
823
|
+
<li>• Proper focus order for all interactive elements</li>
|
|
824
|
+
<li>• Screen reader announcements for state changes</li>
|
|
825
|
+
</ul>
|
|
826
|
+
</div>
|
|
827
|
+
|
|
828
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
829
|
+
<h4 className="mb-2 font-medium text-white">Drag Support</h4>
|
|
830
|
+
<ul className="space-y-1 text-sm text-white/80">
|
|
831
|
+
<li>• Drag to close functionality</li>
|
|
832
|
+
<li>• Smooth animations during drag</li>
|
|
833
|
+
<li>• Haptic feedback on mobile devices</li>
|
|
834
|
+
<li>• Proper gesture recognition</li>
|
|
835
|
+
</ul>
|
|
836
|
+
</div>
|
|
837
|
+
</div>
|
|
838
|
+
|
|
839
|
+
<DrawerFooter>
|
|
840
|
+
<DrawerClose asChild>
|
|
841
|
+
<Button>Close Drawer</Button>
|
|
842
|
+
</DrawerClose>
|
|
843
|
+
</DrawerFooter>
|
|
844
|
+
</DrawerContent>
|
|
845
|
+
</Drawer>
|
|
846
|
+
)
|
|
847
|
+
},
|
|
848
|
+
parameters: {
|
|
849
|
+
docs: {
|
|
850
|
+
description: {
|
|
851
|
+
story:
|
|
852
|
+
"Comprehensive accessibility example showcasing keyboard navigation, focus management, and drag support features.",
|
|
853
|
+
},
|
|
854
|
+
},
|
|
855
|
+
},
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// 7. Drawer without Overlay
|
|
859
|
+
export const DrawerWithoutOverlay: Story = {
|
|
860
|
+
render: () => (
|
|
861
|
+
<div>
|
|
862
|
+
<Drawer>
|
|
863
|
+
<DrawerTrigger asChild>
|
|
864
|
+
<Button className="relative z-10">Open Drawer (No Overlay)</Button>
|
|
865
|
+
</DrawerTrigger>
|
|
866
|
+
<DrawerContent showOverlay={false}>
|
|
867
|
+
<DrawerHeader>
|
|
868
|
+
<DrawerTitle>Drawer Without Overlay</DrawerTitle>
|
|
869
|
+
<DrawerDescription>
|
|
870
|
+
This drawer opens without a backdrop overlay, allowing background
|
|
871
|
+
content to remain visible.
|
|
872
|
+
</DrawerDescription>
|
|
873
|
+
</DrawerHeader>
|
|
874
|
+
<DrawerFooter>
|
|
875
|
+
<Button>Apply Changes</Button>
|
|
876
|
+
<DrawerClose asChild>
|
|
877
|
+
<Button variant="outline">Cancel</Button>
|
|
878
|
+
</DrawerClose>
|
|
879
|
+
</DrawerFooter>
|
|
880
|
+
</DrawerContent>
|
|
881
|
+
</Drawer>
|
|
882
|
+
</div>
|
|
883
|
+
),
|
|
884
|
+
parameters: {
|
|
885
|
+
docs: {
|
|
886
|
+
description: {
|
|
887
|
+
story:
|
|
888
|
+
"Drawer example with `showOverlay={false}` demonstrating how to create non-modal drawer interactions that don't obscure background content.",
|
|
889
|
+
},
|
|
890
|
+
},
|
|
891
|
+
},
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// 8. Overlay Variations
|
|
895
|
+
export const OverlayVariations: Story = {
|
|
896
|
+
render: () => {
|
|
897
|
+
const OverlayDrawer = ({
|
|
898
|
+
opacity,
|
|
899
|
+
glass,
|
|
900
|
+
noise,
|
|
901
|
+
title,
|
|
902
|
+
description,
|
|
903
|
+
}: any) => {
|
|
904
|
+
return (
|
|
905
|
+
<Drawer>
|
|
906
|
+
<DrawerTrigger asChild>
|
|
907
|
+
<Button variant="outline" size="sm">
|
|
908
|
+
{title}
|
|
909
|
+
</Button>
|
|
910
|
+
</DrawerTrigger>
|
|
911
|
+
<DrawerContent
|
|
912
|
+
opacity={opacity}
|
|
913
|
+
glass={glass}
|
|
914
|
+
noise={noise}
|
|
915
|
+
variant="neutral"
|
|
916
|
+
>
|
|
917
|
+
<DrawerHeader>
|
|
918
|
+
<DrawerTitle>{title}</DrawerTitle>
|
|
919
|
+
<DrawerDescription>{description}</DrawerDescription>
|
|
920
|
+
</DrawerHeader>
|
|
921
|
+
<div className="py-4">
|
|
922
|
+
<div className="grid grid-cols-2 gap-2 text-xs text-white/60">
|
|
923
|
+
<div>
|
|
924
|
+
Opacity:{" "}
|
|
925
|
+
<span className="text-white">{opacity || "default"}</span>
|
|
926
|
+
</div>
|
|
927
|
+
<div>
|
|
928
|
+
Glass:{" "}
|
|
929
|
+
<span className="text-white">{glass || "default"}</span>
|
|
930
|
+
</div>
|
|
931
|
+
<div>
|
|
932
|
+
Noise: <span className="text-white">{noise || "none"}</span>
|
|
933
|
+
</div>
|
|
934
|
+
<div>
|
|
935
|
+
Variant: <span className="text-white">neutral</span>
|
|
936
|
+
</div>
|
|
937
|
+
</div>
|
|
938
|
+
</div>
|
|
939
|
+
<DrawerFooter>
|
|
940
|
+
<DrawerClose asChild>
|
|
941
|
+
<Button>Close</Button>
|
|
942
|
+
</DrawerClose>
|
|
943
|
+
</DrawerFooter>
|
|
944
|
+
</DrawerContent>
|
|
945
|
+
</Drawer>
|
|
946
|
+
)
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
return (
|
|
950
|
+
<div className="space-y-8">
|
|
951
|
+
<div className="text-center">
|
|
952
|
+
<h3 className="mb-2 font-medium text-white">Overlay Variations</h3>
|
|
953
|
+
<p className="text-sm text-white/60">
|
|
954
|
+
Different overlay effects for various visual styles
|
|
955
|
+
</p>
|
|
956
|
+
</div>
|
|
957
|
+
|
|
958
|
+
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
|
|
959
|
+
<OverlayDrawer
|
|
960
|
+
opacity="low"
|
|
961
|
+
title="Low Opacity"
|
|
962
|
+
description="Subtle background dimming (40%)"
|
|
963
|
+
/>
|
|
964
|
+
<OverlayDrawer
|
|
965
|
+
opacity="medium"
|
|
966
|
+
title="Medium Opacity"
|
|
967
|
+
description="Balanced background dimming (60%)"
|
|
968
|
+
/>
|
|
969
|
+
<OverlayDrawer
|
|
970
|
+
opacity="high"
|
|
971
|
+
title="High Opacity"
|
|
972
|
+
description="Strong background dimming (80%)"
|
|
973
|
+
/>
|
|
974
|
+
<OverlayDrawer
|
|
975
|
+
opacity="none"
|
|
976
|
+
title="Full Opacity"
|
|
977
|
+
description="Complete background coverage (100%)"
|
|
978
|
+
/>
|
|
979
|
+
<OverlayDrawer
|
|
980
|
+
glass="low"
|
|
981
|
+
title="Low Glass"
|
|
982
|
+
description="Subtle backdrop blur effect"
|
|
983
|
+
/>
|
|
984
|
+
<OverlayDrawer
|
|
985
|
+
glass="medium"
|
|
986
|
+
title="Medium Glass"
|
|
987
|
+
description="Balanced backdrop blur effect"
|
|
988
|
+
/>
|
|
989
|
+
<OverlayDrawer
|
|
990
|
+
glass="high"
|
|
991
|
+
title="High Glass"
|
|
992
|
+
description="Strong backdrop blur effect"
|
|
993
|
+
/>
|
|
994
|
+
<OverlayDrawer
|
|
995
|
+
noise="low"
|
|
996
|
+
title="Low Noise"
|
|
997
|
+
description="Subtle texture pattern"
|
|
998
|
+
/>
|
|
999
|
+
<OverlayDrawer
|
|
1000
|
+
noise="medium"
|
|
1001
|
+
title="Medium Noise"
|
|
1002
|
+
description="Balanced texture pattern"
|
|
1003
|
+
/>
|
|
1004
|
+
<OverlayDrawer
|
|
1005
|
+
noise="high"
|
|
1006
|
+
title="High Noise"
|
|
1007
|
+
description="Strong texture pattern"
|
|
1008
|
+
/>
|
|
1009
|
+
<OverlayDrawer
|
|
1010
|
+
opacity="medium"
|
|
1011
|
+
glass="medium"
|
|
1012
|
+
noise="medium"
|
|
1013
|
+
title="Balanced"
|
|
1014
|
+
description="All effects at medium level"
|
|
1015
|
+
/>
|
|
1016
|
+
</div>
|
|
1017
|
+
</div>
|
|
1018
|
+
)
|
|
1019
|
+
},
|
|
1020
|
+
parameters: {
|
|
1021
|
+
docs: {
|
|
1022
|
+
description: {
|
|
1023
|
+
story:
|
|
1024
|
+
"Showcase of different overlay configurations demonstrating various opacity, glass, and noise effects.",
|
|
1025
|
+
},
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
// 9. Variant Examples
|
|
1031
|
+
export const VariantExamples: Story = {
|
|
1032
|
+
render: () => {
|
|
1033
|
+
return (
|
|
1034
|
+
<div className="space-y-8">
|
|
1035
|
+
<div className="text-center">
|
|
1036
|
+
<h3 className="mb-2 font-medium text-white">Drawer Variants</h3>
|
|
1037
|
+
<p className="text-sm text-white/60">
|
|
1038
|
+
Compare the neutral (default) and gradient variants
|
|
1039
|
+
</p>
|
|
1040
|
+
</div>
|
|
1041
|
+
|
|
1042
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
1043
|
+
<div className="space-y-4">
|
|
1044
|
+
<h4 className="text-center font-medium text-white">
|
|
1045
|
+
Neutral Variant (Default)
|
|
1046
|
+
</h4>
|
|
1047
|
+
<Drawer>
|
|
1048
|
+
<DrawerTrigger asChild>
|
|
1049
|
+
<Button variant="outline" className="w-full">
|
|
1050
|
+
Open Neutral Drawer
|
|
1051
|
+
</Button>
|
|
1052
|
+
</DrawerTrigger>
|
|
1053
|
+
<DrawerContent variant="neutral">
|
|
1054
|
+
<DrawerHeader>
|
|
1055
|
+
<DrawerTitle>Neutral Variant</DrawerTitle>
|
|
1056
|
+
<DrawerDescription>
|
|
1057
|
+
This is the default neutral variant with frosted glass
|
|
1058
|
+
background and border.
|
|
1059
|
+
</DrawerDescription>
|
|
1060
|
+
</DrawerHeader>
|
|
1061
|
+
<div className="py-4">
|
|
1062
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
1063
|
+
<h5 className="mb-2 font-medium text-white">Features:</h5>
|
|
1064
|
+
<ul className="space-y-1 text-sm text-white/70">
|
|
1065
|
+
<li>• Frosted glass background</li>
|
|
1066
|
+
<li>• Subtle border</li>
|
|
1067
|
+
<li>• Backdrop blur effect</li>
|
|
1068
|
+
<li>• Semi-transparent appearance</li>
|
|
1069
|
+
</ul>
|
|
1070
|
+
</div>
|
|
1071
|
+
</div>
|
|
1072
|
+
<DrawerFooter>
|
|
1073
|
+
<DrawerClose asChild>
|
|
1074
|
+
<Button>Close</Button>
|
|
1075
|
+
</DrawerClose>
|
|
1076
|
+
</DrawerFooter>
|
|
1077
|
+
</DrawerContent>
|
|
1078
|
+
</Drawer>
|
|
1079
|
+
</div>
|
|
1080
|
+
|
|
1081
|
+
<div className="space-y-4">
|
|
1082
|
+
<h4 className="text-center font-medium text-white">
|
|
1083
|
+
Gradient Variant
|
|
1084
|
+
</h4>
|
|
1085
|
+
<Drawer>
|
|
1086
|
+
<DrawerTrigger asChild>
|
|
1087
|
+
<Button variant="outline" className="w-full">
|
|
1088
|
+
Open Gradient Drawer
|
|
1089
|
+
</Button>
|
|
1090
|
+
</DrawerTrigger>
|
|
1091
|
+
<DrawerContent variant="gradient">
|
|
1092
|
+
<DrawerHeader>
|
|
1093
|
+
<DrawerTitle>Gradient Variant</DrawerTitle>
|
|
1094
|
+
<DrawerDescription>
|
|
1095
|
+
This is the gradient variant with white gradient background
|
|
1096
|
+
and no border.
|
|
1097
|
+
</DrawerDescription>
|
|
1098
|
+
</DrawerHeader>
|
|
1099
|
+
<div className="py-4">
|
|
1100
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
1101
|
+
<h5 className="mb-2 font-medium text-white">Features:</h5>
|
|
1102
|
+
<ul className="space-y-1 text-sm text-white/70">
|
|
1103
|
+
<li>• White gradient background</li>
|
|
1104
|
+
<li>• No border</li>
|
|
1105
|
+
<li>• Clean, modern appearance</li>
|
|
1106
|
+
<li>• Solid background effect</li>
|
|
1107
|
+
</ul>
|
|
1108
|
+
</div>
|
|
1109
|
+
</div>
|
|
1110
|
+
<DrawerFooter>
|
|
1111
|
+
<DrawerClose asChild>
|
|
1112
|
+
<Button>Close</Button>
|
|
1113
|
+
</DrawerClose>
|
|
1114
|
+
</DrawerFooter>
|
|
1115
|
+
</DrawerContent>
|
|
1116
|
+
</Drawer>
|
|
1117
|
+
</div>
|
|
1118
|
+
</div>
|
|
1119
|
+
</div>
|
|
1120
|
+
)
|
|
1121
|
+
},
|
|
1122
|
+
parameters: {
|
|
1123
|
+
docs: {
|
|
1124
|
+
description: {
|
|
1125
|
+
story:
|
|
1126
|
+
"Simple comparison of the two drawer variants: neutral (default) with frosted glass background and gradient with white gradient background.",
|
|
1127
|
+
},
|
|
1128
|
+
},
|
|
1129
|
+
},
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
export const DrawerWithSwipeButton: Story = {
|
|
1133
|
+
render: () => (
|
|
1134
|
+
<div>
|
|
1135
|
+
<Drawer>
|
|
1136
|
+
<DrawerTrigger asChild>
|
|
1137
|
+
<Button className="relative z-10">
|
|
1138
|
+
Open Drawer (With Swipe button)
|
|
1139
|
+
</Button>
|
|
1140
|
+
</DrawerTrigger>
|
|
1141
|
+
<DrawerContent showSwipeButton={true}>
|
|
1142
|
+
<DrawerHeader>
|
|
1143
|
+
<DrawerTitle>Drawer with Swipe button</DrawerTitle>
|
|
1144
|
+
<DrawerDescription>
|
|
1145
|
+
This drawer opens with a swipe button.
|
|
1146
|
+
</DrawerDescription>
|
|
1147
|
+
</DrawerHeader>
|
|
1148
|
+
<DrawerFooter>
|
|
1149
|
+
<Button>Apply Changes</Button>
|
|
1150
|
+
<DrawerClose asChild>
|
|
1151
|
+
<Button variant="outline">Cancel</Button>
|
|
1152
|
+
</DrawerClose>
|
|
1153
|
+
</DrawerFooter>
|
|
1154
|
+
</DrawerContent>
|
|
1155
|
+
</Drawer>
|
|
1156
|
+
</div>
|
|
1157
|
+
),
|
|
1158
|
+
parameters: {
|
|
1159
|
+
docs: {
|
|
1160
|
+
description: {
|
|
1161
|
+
story:
|
|
1162
|
+
"Drawer example with `showSwipeButton={true}` showing a swipe indicator button",
|
|
1163
|
+
},
|
|
1164
|
+
},
|
|
1165
|
+
},
|
|
1166
|
+
}
|