@djangocfg/ui-core 2.1.382 → 2.1.384
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/package.json +5 -12
- package/src/components/boundary/boundary.story.tsx +0 -191
- package/src/components/data/avatar/avatar.story.tsx +0 -115
- package/src/components/data/badge/badge.story.tsx +0 -56
- package/src/components/data/calendar/calendar.story.tsx +0 -127
- package/src/components/data/carousel/carousel.story.tsx +0 -122
- package/src/components/data/progress/progress.story.tsx +0 -97
- package/src/components/data/table/table.story.tsx +0 -148
- package/src/components/data/toggle/toggle.story.tsx +0 -104
- package/src/components/data/toggle-group/toggle-group.story.tsx +0 -118
- package/src/components/feedback/alert/alert.story.tsx +0 -77
- package/src/components/feedback/empty/empty.story.tsx +0 -115
- package/src/components/feedback/preloader/preloader.story.tsx +0 -86
- package/src/components/feedback/spinner/spinner.story.tsx +0 -66
- package/src/components/forms/button/button.story.tsx +0 -116
- package/src/components/forms/button-download/button-download.story.tsx +0 -112
- package/src/components/forms/button-group/button-group.story.tsx +0 -79
- package/src/components/forms/checkbox/checkbox.story.tsx +0 -89
- package/src/components/forms/input/input.story.tsx +0 -77
- package/src/components/forms/input-group/input-group.story.tsx +0 -119
- package/src/components/forms/input-otp/input-otp.story.tsx +0 -105
- package/src/components/forms/label/label.story.tsx +0 -52
- package/src/components/forms/radio-group/radio-group.story.tsx +0 -113
- package/src/components/forms/slider/slider.story.tsx +0 -134
- package/src/components/forms/switch/switch.story.tsx +0 -98
- package/src/components/forms/textarea/textarea.story.tsx +0 -94
- package/src/components/layout/aspect-ratio/aspect-ratio.story.tsx +0 -94
- package/src/components/layout/card/card.story.tsx +0 -105
- package/src/components/layout/resizable/resizable.story.tsx +0 -119
- package/src/components/layout/scroll-area/scroll-area.story.tsx +0 -172
- package/src/components/layout/separator/separator.story.tsx +0 -69
- package/src/components/layout/skeleton/skeleton.story.tsx +0 -101
- package/src/components/navigation/accordion/accordion.story.tsx +0 -110
- package/src/components/navigation/collapsible/collapsible.story.tsx +0 -133
- package/src/components/navigation/command/command.story.tsx +0 -121
- package/src/components/navigation/context-menu/context-menu.story.tsx +0 -125
- package/src/components/navigation/dropdown-menu/dropdown-menu.story.tsx +0 -208
- package/src/components/navigation/menubar/menubar.story.tsx +0 -152
- package/src/components/navigation/navigation-menu/navigation-menu.story.tsx +0 -154
- package/src/components/navigation/tabs/tabs.story.tsx +0 -98
- package/src/components/overlay/alert-dialog/alert-dialog.story.tsx +0 -104
- package/src/components/overlay/dialog/dialog.story.tsx +0 -212
- package/src/components/overlay/drawer/drawer.story.tsx +0 -359
- package/src/components/overlay/hover-card/hover-card.story.tsx +0 -102
- package/src/components/overlay/popover/popover.story.tsx +0 -127
- package/src/components/overlay/responsive-sheet/responsive-sheet.story.tsx +0 -117
- package/src/components/overlay/sheet/sheet.story.tsx +0 -148
- package/src/components/overlay/tooltip/tooltip.story.tsx +0 -139
- package/src/components/select/combobox-async.story.tsx +0 -215
- package/src/components/select/combobox.story.tsx +0 -226
- package/src/components/select/country-select.story.tsx +0 -261
- package/src/components/select/language-select.story.tsx +0 -264
- package/src/components/select/multi-select.story.tsx +0 -122
- package/src/components/select/select.story.tsx +0 -112
- package/src/components/specialized/copy/copy.story.tsx +0 -77
- package/src/components/specialized/flag/flag.story.tsx +0 -82
- package/src/components/specialized/image-with-fallback/image-with-fallback.story.tsx +0 -105
- package/src/components/specialized/kbd/kbd.story.tsx +0 -113
- package/src/lib/dialog-service/dialog-service.story.tsx +0 -263
- package/src/stories/index.ts +0 -28
- package/src/styles/theme/theme-tokens.story.tsx +0 -157
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { defineStory } from '@djangocfg/playground';
|
|
2
|
-
import {
|
|
3
|
-
AlertDialog,
|
|
4
|
-
AlertDialogTrigger,
|
|
5
|
-
AlertDialogContent,
|
|
6
|
-
AlertDialogHeader,
|
|
7
|
-
AlertDialogFooter,
|
|
8
|
-
AlertDialogTitle,
|
|
9
|
-
AlertDialogDescription,
|
|
10
|
-
AlertDialogAction,
|
|
11
|
-
AlertDialogCancel,
|
|
12
|
-
} from '.';
|
|
13
|
-
import { Button } from '../../forms/button';
|
|
14
|
-
|
|
15
|
-
export default defineStory({
|
|
16
|
-
title: 'Core/Alert Dialog',
|
|
17
|
-
component: AlertDialog,
|
|
18
|
-
description: 'Modal dialog for important confirmations.',
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
export const Default = () => (
|
|
22
|
-
<AlertDialog>
|
|
23
|
-
<AlertDialogTrigger asChild>
|
|
24
|
-
<Button variant="outline">Show Dialog</Button>
|
|
25
|
-
</AlertDialogTrigger>
|
|
26
|
-
<AlertDialogContent>
|
|
27
|
-
<AlertDialogHeader>
|
|
28
|
-
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
|
29
|
-
<AlertDialogDescription>
|
|
30
|
-
This action cannot be undone. This will permanently delete your
|
|
31
|
-
account and remove your data from our servers.
|
|
32
|
-
</AlertDialogDescription>
|
|
33
|
-
</AlertDialogHeader>
|
|
34
|
-
<AlertDialogFooter>
|
|
35
|
-
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
36
|
-
<AlertDialogAction>Continue</AlertDialogAction>
|
|
37
|
-
</AlertDialogFooter>
|
|
38
|
-
</AlertDialogContent>
|
|
39
|
-
</AlertDialog>
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
export const Destructive = () => (
|
|
43
|
-
<AlertDialog>
|
|
44
|
-
<AlertDialogTrigger asChild>
|
|
45
|
-
<Button variant="destructive">Delete Account</Button>
|
|
46
|
-
</AlertDialogTrigger>
|
|
47
|
-
<AlertDialogContent>
|
|
48
|
-
<AlertDialogHeader>
|
|
49
|
-
<AlertDialogTitle>Delete Account</AlertDialogTitle>
|
|
50
|
-
<AlertDialogDescription>
|
|
51
|
-
Are you sure you want to delete your account? All of your data will be
|
|
52
|
-
permanently removed. This action cannot be undone.
|
|
53
|
-
</AlertDialogDescription>
|
|
54
|
-
</AlertDialogHeader>
|
|
55
|
-
<AlertDialogFooter>
|
|
56
|
-
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
57
|
-
<AlertDialogAction className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
|
|
58
|
-
Delete
|
|
59
|
-
</AlertDialogAction>
|
|
60
|
-
</AlertDialogFooter>
|
|
61
|
-
</AlertDialogContent>
|
|
62
|
-
</AlertDialog>
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
export const SaveChanges = () => (
|
|
66
|
-
<AlertDialog>
|
|
67
|
-
<AlertDialogTrigger asChild>
|
|
68
|
-
<Button>Leave Page</Button>
|
|
69
|
-
</AlertDialogTrigger>
|
|
70
|
-
<AlertDialogContent>
|
|
71
|
-
<AlertDialogHeader>
|
|
72
|
-
<AlertDialogTitle>Unsaved Changes</AlertDialogTitle>
|
|
73
|
-
<AlertDialogDescription>
|
|
74
|
-
You have unsaved changes. Are you sure you want to leave? Your changes
|
|
75
|
-
will be lost.
|
|
76
|
-
</AlertDialogDescription>
|
|
77
|
-
</AlertDialogHeader>
|
|
78
|
-
<AlertDialogFooter>
|
|
79
|
-
<AlertDialogCancel>Stay</AlertDialogCancel>
|
|
80
|
-
<AlertDialogAction>Leave</AlertDialogAction>
|
|
81
|
-
</AlertDialogFooter>
|
|
82
|
-
</AlertDialogContent>
|
|
83
|
-
</AlertDialog>
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
export const Logout = () => (
|
|
87
|
-
<AlertDialog>
|
|
88
|
-
<AlertDialogTrigger asChild>
|
|
89
|
-
<Button variant="ghost">Log Out</Button>
|
|
90
|
-
</AlertDialogTrigger>
|
|
91
|
-
<AlertDialogContent>
|
|
92
|
-
<AlertDialogHeader>
|
|
93
|
-
<AlertDialogTitle>Log out</AlertDialogTitle>
|
|
94
|
-
<AlertDialogDescription>
|
|
95
|
-
Are you sure you want to log out of your account?
|
|
96
|
-
</AlertDialogDescription>
|
|
97
|
-
</AlertDialogHeader>
|
|
98
|
-
<AlertDialogFooter>
|
|
99
|
-
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
100
|
-
<AlertDialogAction>Log Out</AlertDialogAction>
|
|
101
|
-
</AlertDialogFooter>
|
|
102
|
-
</AlertDialogContent>
|
|
103
|
-
</AlertDialog>
|
|
104
|
-
);
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { ArrowLeft, X } from 'lucide-react';
|
|
2
|
-
import { defineStory } from '@djangocfg/playground';
|
|
3
|
-
import {
|
|
4
|
-
Dialog,
|
|
5
|
-
DialogTrigger,
|
|
6
|
-
DialogContent,
|
|
7
|
-
DialogHeader,
|
|
8
|
-
DialogFooter,
|
|
9
|
-
DialogTitle,
|
|
10
|
-
DialogDescription,
|
|
11
|
-
DialogClose,
|
|
12
|
-
} from '.';
|
|
13
|
-
import { Button } from '../../forms/button';
|
|
14
|
-
import { Input } from '../../forms/input';
|
|
15
|
-
import { Label } from '../../forms/label';
|
|
16
|
-
|
|
17
|
-
export default defineStory({
|
|
18
|
-
title: 'Core/Dialog',
|
|
19
|
-
component: Dialog,
|
|
20
|
-
description: 'Modal dialog for focused interactions.',
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
export const Default = () => (
|
|
24
|
-
<Dialog>
|
|
25
|
-
<DialogTrigger asChild>
|
|
26
|
-
<Button variant="outline">Open Dialog</Button>
|
|
27
|
-
</DialogTrigger>
|
|
28
|
-
<DialogContent>
|
|
29
|
-
<DialogHeader>
|
|
30
|
-
<DialogTitle>Dialog Title</DialogTitle>
|
|
31
|
-
<DialogDescription>
|
|
32
|
-
This is a dialog description. It explains what this dialog is about.
|
|
33
|
-
</DialogDescription>
|
|
34
|
-
</DialogHeader>
|
|
35
|
-
<div className="py-4">
|
|
36
|
-
<p>Dialog content goes here.</p>
|
|
37
|
-
</div>
|
|
38
|
-
<DialogFooter>
|
|
39
|
-
<DialogClose asChild>
|
|
40
|
-
<Button variant="outline">Cancel</Button>
|
|
41
|
-
</DialogClose>
|
|
42
|
-
<Button>Confirm</Button>
|
|
43
|
-
</DialogFooter>
|
|
44
|
-
</DialogContent>
|
|
45
|
-
</Dialog>
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
export const EditProfile = () => (
|
|
49
|
-
<Dialog>
|
|
50
|
-
<DialogTrigger asChild>
|
|
51
|
-
<Button>Edit Profile</Button>
|
|
52
|
-
</DialogTrigger>
|
|
53
|
-
<DialogContent className="sm:max-w-md">
|
|
54
|
-
<DialogHeader>
|
|
55
|
-
<DialogTitle>Edit Profile</DialogTitle>
|
|
56
|
-
<DialogDescription>
|
|
57
|
-
Make changes to your profile here. Click save when you're done.
|
|
58
|
-
</DialogDescription>
|
|
59
|
-
</DialogHeader>
|
|
60
|
-
<div className="space-y-4 py-4">
|
|
61
|
-
<div className="space-y-2">
|
|
62
|
-
<Label htmlFor="name">Name</Label>
|
|
63
|
-
<Input id="name" defaultValue="John Doe" />
|
|
64
|
-
</div>
|
|
65
|
-
<div className="space-y-2">
|
|
66
|
-
<Label htmlFor="email">Email</Label>
|
|
67
|
-
<Input id="email" type="email" defaultValue="john@example.com" />
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
<DialogFooter>
|
|
71
|
-
<DialogClose asChild>
|
|
72
|
-
<Button variant="outline">Cancel</Button>
|
|
73
|
-
</DialogClose>
|
|
74
|
-
<Button>Save Changes</Button>
|
|
75
|
-
</DialogFooter>
|
|
76
|
-
</DialogContent>
|
|
77
|
-
</Dialog>
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
export const Confirmation = () => (
|
|
81
|
-
<Dialog>
|
|
82
|
-
<DialogTrigger asChild>
|
|
83
|
-
<Button variant="destructive">Delete Account</Button>
|
|
84
|
-
</DialogTrigger>
|
|
85
|
-
<DialogContent>
|
|
86
|
-
<DialogHeader>
|
|
87
|
-
<DialogTitle>Are you sure?</DialogTitle>
|
|
88
|
-
<DialogDescription>
|
|
89
|
-
This action cannot be undone. This will permanently delete your account
|
|
90
|
-
and remove all your data from our servers.
|
|
91
|
-
</DialogDescription>
|
|
92
|
-
</DialogHeader>
|
|
93
|
-
<DialogFooter>
|
|
94
|
-
<DialogClose asChild>
|
|
95
|
-
<Button variant="outline">Cancel</Button>
|
|
96
|
-
</DialogClose>
|
|
97
|
-
<Button variant="destructive">Delete Account</Button>
|
|
98
|
-
</DialogFooter>
|
|
99
|
-
</DialogContent>
|
|
100
|
-
</Dialog>
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
export const Fullscreen = () => (
|
|
104
|
-
<Dialog>
|
|
105
|
-
<DialogTrigger asChild>
|
|
106
|
-
<Button variant="outline">Open fullscreen dialog</Button>
|
|
107
|
-
</DialogTrigger>
|
|
108
|
-
<DialogContent fullscreen>
|
|
109
|
-
<div className="mx-auto flex h-full w-full max-w-3xl flex-col px-4 py-10 sm:px-6 lg:px-8">
|
|
110
|
-
<DialogTitle className="text-2xl font-semibold tracking-tight">
|
|
111
|
-
Fullscreen layout
|
|
112
|
-
</DialogTitle>
|
|
113
|
-
<DialogDescription className="mt-1 text-muted-foreground">
|
|
114
|
-
`fullscreen` removes the centred-card chrome and stretches the content to
|
|
115
|
-
the viewport. Build your own header / footer inside.
|
|
116
|
-
</DialogDescription>
|
|
117
|
-
<div className="mt-6 flex-1 rounded-xl border border-dashed border-border/60 bg-muted/30 p-6 text-sm text-muted-foreground">
|
|
118
|
-
Slot for a custom layout — gallery, onboarding, command palette, etc.
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
</DialogContent>
|
|
122
|
-
</Dialog>
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
export const CustomCloseButton = () => (
|
|
126
|
-
<Dialog>
|
|
127
|
-
<DialogTrigger asChild>
|
|
128
|
-
<Button variant="outline">Open with pill close</Button>
|
|
129
|
-
</DialogTrigger>
|
|
130
|
-
<DialogContent
|
|
131
|
-
fullscreen
|
|
132
|
-
closeButton={
|
|
133
|
-
<DialogClose
|
|
134
|
-
aria-label="Close"
|
|
135
|
-
className="absolute right-4 top-4 inline-flex h-10 w-10 cursor-pointer items-center justify-center rounded-full border border-border/60 bg-background/90 text-muted-foreground shadow-sm transition-colors hover:bg-accent hover:text-foreground"
|
|
136
|
-
>
|
|
137
|
-
<X className="h-4 w-4" />
|
|
138
|
-
</DialogClose>
|
|
139
|
-
}
|
|
140
|
-
>
|
|
141
|
-
<div className="mx-auto flex h-full w-full max-w-2xl flex-col px-4 py-10">
|
|
142
|
-
<DialogTitle>Custom close affordance</DialogTitle>
|
|
143
|
-
<DialogDescription className="mt-1 text-muted-foreground">
|
|
144
|
-
Pass `closeButton` to override the default Radix `X`. Pass `false` to
|
|
145
|
-
drop the affordance entirely.
|
|
146
|
-
</DialogDescription>
|
|
147
|
-
</div>
|
|
148
|
-
</DialogContent>
|
|
149
|
-
</Dialog>
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
export const NoCloseButton = () => (
|
|
153
|
-
<Dialog>
|
|
154
|
-
<DialogTrigger asChild>
|
|
155
|
-
<Button variant="outline">Modal step (no close)</Button>
|
|
156
|
-
</DialogTrigger>
|
|
157
|
-
<DialogContent closeButton={false}>
|
|
158
|
-
<DialogHeader>
|
|
159
|
-
<DialogTitle>Saving…</DialogTitle>
|
|
160
|
-
<DialogDescription>
|
|
161
|
-
The dialog has no close affordance — dismissal is driven by the action
|
|
162
|
-
buttons below or programmatically.
|
|
163
|
-
</DialogDescription>
|
|
164
|
-
</DialogHeader>
|
|
165
|
-
<DialogFooter>
|
|
166
|
-
<DialogClose asChild>
|
|
167
|
-
<Button variant="outline">
|
|
168
|
-
<ArrowLeft className="mr-1.5 h-3.5 w-3.5" />
|
|
169
|
-
Back
|
|
170
|
-
</Button>
|
|
171
|
-
</DialogClose>
|
|
172
|
-
</DialogFooter>
|
|
173
|
-
</DialogContent>
|
|
174
|
-
</Dialog>
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
export const LongContent = () => (
|
|
178
|
-
<Dialog>
|
|
179
|
-
<DialogTrigger asChild>
|
|
180
|
-
<Button variant="outline">Terms of Service</Button>
|
|
181
|
-
</DialogTrigger>
|
|
182
|
-
<DialogContent className="max-h-[80vh] overflow-y-auto">
|
|
183
|
-
<DialogHeader>
|
|
184
|
-
<DialogTitle>Terms of Service</DialogTitle>
|
|
185
|
-
</DialogHeader>
|
|
186
|
-
<div className="space-y-4 py-4 text-sm text-muted-foreground">
|
|
187
|
-
<p>
|
|
188
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
|
|
189
|
-
tempor incididunt ut labore et dolore magna aliqua.
|
|
190
|
-
</p>
|
|
191
|
-
<p>
|
|
192
|
-
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
|
|
193
|
-
ut aliquip ex ea commodo consequat.
|
|
194
|
-
</p>
|
|
195
|
-
<p>
|
|
196
|
-
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
|
197
|
-
dolore eu fugiat nulla pariatur.
|
|
198
|
-
</p>
|
|
199
|
-
<p>
|
|
200
|
-
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
|
|
201
|
-
deserunt mollit anim id est laborum.
|
|
202
|
-
</p>
|
|
203
|
-
</div>
|
|
204
|
-
<DialogFooter>
|
|
205
|
-
<DialogClose asChild>
|
|
206
|
-
<Button variant="outline">Decline</Button>
|
|
207
|
-
</DialogClose>
|
|
208
|
-
<Button>Accept</Button>
|
|
209
|
-
</DialogFooter>
|
|
210
|
-
</DialogContent>
|
|
211
|
-
</Dialog>
|
|
212
|
-
);
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { defineStory, useSelect } from '@djangocfg/playground';
|
|
3
|
-
import {
|
|
4
|
-
Drawer,
|
|
5
|
-
DrawerTrigger,
|
|
6
|
-
DrawerContent,
|
|
7
|
-
DrawerHeader,
|
|
8
|
-
DrawerFooter,
|
|
9
|
-
DrawerTitle,
|
|
10
|
-
DrawerDescription,
|
|
11
|
-
DrawerClose,
|
|
12
|
-
useDrawerSize,
|
|
13
|
-
type DrawerSize,
|
|
14
|
-
} from '.';
|
|
15
|
-
import { Button } from '../../forms/button';
|
|
16
|
-
import { Input } from '../../forms/input';
|
|
17
|
-
import { Label } from '../../forms/label';
|
|
18
|
-
|
|
19
|
-
export default defineStory({
|
|
20
|
-
title: 'Core/Drawer',
|
|
21
|
-
component: Drawer,
|
|
22
|
-
description: 'Mobile-friendly drawer that slides up from the bottom.',
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export const Default = () => (
|
|
26
|
-
<Drawer>
|
|
27
|
-
<DrawerTrigger asChild>
|
|
28
|
-
<Button variant="outline">Open Drawer</Button>
|
|
29
|
-
</DrawerTrigger>
|
|
30
|
-
<DrawerContent>
|
|
31
|
-
<DrawerHeader>
|
|
32
|
-
<DrawerTitle>Drawer Title</DrawerTitle>
|
|
33
|
-
<DrawerDescription>
|
|
34
|
-
This is a description of the drawer content.
|
|
35
|
-
</DrawerDescription>
|
|
36
|
-
</DrawerHeader>
|
|
37
|
-
<div className="p-4">
|
|
38
|
-
<p>Drawer content goes here.</p>
|
|
39
|
-
</div>
|
|
40
|
-
<DrawerFooter>
|
|
41
|
-
<Button>Submit</Button>
|
|
42
|
-
<DrawerClose asChild>
|
|
43
|
-
<Button variant="outline">Cancel</Button>
|
|
44
|
-
</DrawerClose>
|
|
45
|
-
</DrawerFooter>
|
|
46
|
-
</DrawerContent>
|
|
47
|
-
</Drawer>
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
export const WithForm = () => (
|
|
51
|
-
<Drawer>
|
|
52
|
-
<DrawerTrigger asChild>
|
|
53
|
-
<Button>Edit Profile</Button>
|
|
54
|
-
</DrawerTrigger>
|
|
55
|
-
<DrawerContent>
|
|
56
|
-
<DrawerHeader>
|
|
57
|
-
<DrawerTitle>Edit Profile</DrawerTitle>
|
|
58
|
-
<DrawerDescription>
|
|
59
|
-
Make changes to your profile information.
|
|
60
|
-
</DrawerDescription>
|
|
61
|
-
</DrawerHeader>
|
|
62
|
-
<div className="p-4 space-y-4">
|
|
63
|
-
<div className="space-y-2">
|
|
64
|
-
<Label htmlFor="name">Name</Label>
|
|
65
|
-
<Input id="name" defaultValue="John Doe" />
|
|
66
|
-
</div>
|
|
67
|
-
<div className="space-y-2">
|
|
68
|
-
<Label htmlFor="email">Email</Label>
|
|
69
|
-
<Input id="email" type="email" defaultValue="john@example.com" />
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
<DrawerFooter>
|
|
73
|
-
<Button>Save Changes</Button>
|
|
74
|
-
<DrawerClose asChild>
|
|
75
|
-
<Button variant="outline">Cancel</Button>
|
|
76
|
-
</DrawerClose>
|
|
77
|
-
</DrawerFooter>
|
|
78
|
-
</DrawerContent>
|
|
79
|
-
</Drawer>
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
export const Confirmation = () => (
|
|
83
|
-
<Drawer>
|
|
84
|
-
<DrawerTrigger asChild>
|
|
85
|
-
<Button variant="destructive">Delete Account</Button>
|
|
86
|
-
</DrawerTrigger>
|
|
87
|
-
<DrawerContent>
|
|
88
|
-
<DrawerHeader>
|
|
89
|
-
<DrawerTitle>Are you sure?</DrawerTitle>
|
|
90
|
-
<DrawerDescription>
|
|
91
|
-
This action cannot be undone. Your account and all associated data will be permanently deleted.
|
|
92
|
-
</DrawerDescription>
|
|
93
|
-
</DrawerHeader>
|
|
94
|
-
<DrawerFooter>
|
|
95
|
-
<Button variant="destructive">Yes, Delete My Account</Button>
|
|
96
|
-
<DrawerClose asChild>
|
|
97
|
-
<Button variant="outline">Cancel</Button>
|
|
98
|
-
</DrawerClose>
|
|
99
|
-
</DrawerFooter>
|
|
100
|
-
</DrawerContent>
|
|
101
|
-
</Drawer>
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
export const ActionSheet = () => (
|
|
105
|
-
<Drawer>
|
|
106
|
-
<DrawerTrigger asChild>
|
|
107
|
-
<Button variant="outline">Share</Button>
|
|
108
|
-
</DrawerTrigger>
|
|
109
|
-
<DrawerContent>
|
|
110
|
-
<DrawerHeader>
|
|
111
|
-
<DrawerTitle>Share this item</DrawerTitle>
|
|
112
|
-
</DrawerHeader>
|
|
113
|
-
<div className="p-4 space-y-2">
|
|
114
|
-
<Button variant="ghost" className="w-full justify-start">
|
|
115
|
-
Copy Link
|
|
116
|
-
</Button>
|
|
117
|
-
<Button variant="ghost" className="w-full justify-start">
|
|
118
|
-
Share to Twitter
|
|
119
|
-
</Button>
|
|
120
|
-
<Button variant="ghost" className="w-full justify-start">
|
|
121
|
-
Share to Facebook
|
|
122
|
-
</Button>
|
|
123
|
-
<Button variant="ghost" className="w-full justify-start">
|
|
124
|
-
Send via Email
|
|
125
|
-
</Button>
|
|
126
|
-
</div>
|
|
127
|
-
<DrawerFooter>
|
|
128
|
-
<DrawerClose asChild>
|
|
129
|
-
<Button variant="outline" className="w-full">Cancel</Button>
|
|
130
|
-
</DrawerClose>
|
|
131
|
-
</DrawerFooter>
|
|
132
|
-
</DrawerContent>
|
|
133
|
-
</Drawer>
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
const SIZES: readonly DrawerSize[] = ['sm', 'md', 'lg', 'xl', 'full'] as const;
|
|
137
|
-
|
|
138
|
-
export const Sizes = () => {
|
|
139
|
-
const [size, setSize] = React.useState<DrawerSize>('md');
|
|
140
|
-
const [open, setOpen] = React.useState(false);
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<div className="space-y-4">
|
|
144
|
-
<div className="flex flex-wrap gap-2">
|
|
145
|
-
{SIZES.map((s) => (
|
|
146
|
-
<Button
|
|
147
|
-
key={s}
|
|
148
|
-
variant={size === s ? 'default' : 'outline'}
|
|
149
|
-
onClick={() => {
|
|
150
|
-
setSize(s);
|
|
151
|
-
setOpen(true);
|
|
152
|
-
}}
|
|
153
|
-
>
|
|
154
|
-
{s}
|
|
155
|
-
</Button>
|
|
156
|
-
))}
|
|
157
|
-
</div>
|
|
158
|
-
<p className="text-sm text-muted-foreground">
|
|
159
|
-
Current size: <code>{size}</code>. Direction: right.
|
|
160
|
-
</p>
|
|
161
|
-
<Drawer open={open} onOpenChange={setOpen} direction="right">
|
|
162
|
-
<DrawerContent direction="right" size={size}>
|
|
163
|
-
<DrawerHeader>
|
|
164
|
-
<DrawerTitle>Size: {size}</DrawerTitle>
|
|
165
|
-
<DrawerDescription>
|
|
166
|
-
Width preset is applied via inline style — vaul measures it
|
|
167
|
-
correctly on first paint.
|
|
168
|
-
</DrawerDescription>
|
|
169
|
-
</DrawerHeader>
|
|
170
|
-
<div className="p-4 text-sm">Content adapts to the chosen size.</div>
|
|
171
|
-
<DrawerFooter>
|
|
172
|
-
<DrawerClose asChild>
|
|
173
|
-
<Button variant="outline">Close</Button>
|
|
174
|
-
</DrawerClose>
|
|
175
|
-
</DrawerFooter>
|
|
176
|
-
</DrawerContent>
|
|
177
|
-
</Drawer>
|
|
178
|
-
</div>
|
|
179
|
-
);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
export const Directions = () => {
|
|
183
|
-
const [direction] = useSelect('direction', {
|
|
184
|
-
options: ['top', 'right', 'bottom', 'left'] as const,
|
|
185
|
-
defaultValue: 'right',
|
|
186
|
-
label: 'Direction',
|
|
187
|
-
description: 'Edge from which the drawer slides.',
|
|
188
|
-
});
|
|
189
|
-
const [size] = useSelect('size', {
|
|
190
|
-
options: ['sm', 'md', 'lg', 'xl', 'full'] as const,
|
|
191
|
-
defaultValue: 'md',
|
|
192
|
-
label: 'Size',
|
|
193
|
-
description: 'Width (left/right) or height (top/bottom).',
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
return (
|
|
197
|
-
<Drawer direction={direction}>
|
|
198
|
-
<DrawerTrigger asChild>
|
|
199
|
-
<Button variant="outline">Open from {direction}</Button>
|
|
200
|
-
</DrawerTrigger>
|
|
201
|
-
<DrawerContent direction={direction} size={size}>
|
|
202
|
-
<DrawerHeader>
|
|
203
|
-
<DrawerTitle>Direction: {direction}</DrawerTitle>
|
|
204
|
-
<DrawerDescription>
|
|
205
|
-
Size presets adapt: horizontal directions size width, vertical
|
|
206
|
-
ones size height.
|
|
207
|
-
</DrawerDescription>
|
|
208
|
-
</DrawerHeader>
|
|
209
|
-
<div className="p-4 text-sm">size = {size}</div>
|
|
210
|
-
<DrawerFooter>
|
|
211
|
-
<DrawerClose asChild>
|
|
212
|
-
<Button variant="outline">Close</Button>
|
|
213
|
-
</DrawerClose>
|
|
214
|
-
</DrawerFooter>
|
|
215
|
-
</DrawerContent>
|
|
216
|
-
</Drawer>
|
|
217
|
-
);
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
export const CustomWidth = () => (
|
|
221
|
-
<Drawer direction="right">
|
|
222
|
-
<DrawerTrigger asChild>
|
|
223
|
-
<Button variant="outline">Open with width=720px</Button>
|
|
224
|
-
</DrawerTrigger>
|
|
225
|
-
<DrawerContent direction="right" width="720px">
|
|
226
|
-
<DrawerHeader>
|
|
227
|
-
<DrawerTitle>Custom width</DrawerTitle>
|
|
228
|
-
<DrawerDescription>
|
|
229
|
-
Explicit <code>width</code> overrides the <code>size</code> preset.
|
|
230
|
-
</DrawerDescription>
|
|
231
|
-
</DrawerHeader>
|
|
232
|
-
<div className="p-4 text-sm">Width is exactly 720px.</div>
|
|
233
|
-
<DrawerFooter>
|
|
234
|
-
<DrawerClose asChild>
|
|
235
|
-
<Button variant="outline">Close</Button>
|
|
236
|
-
</DrawerClose>
|
|
237
|
-
</DrawerFooter>
|
|
238
|
-
</DrawerContent>
|
|
239
|
-
</Drawer>
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
export const Resizable = () => {
|
|
243
|
-
const [size, setSize] = React.useState<number | null>(null);
|
|
244
|
-
return (
|
|
245
|
-
<div className="space-y-3">
|
|
246
|
-
<p className="text-sm text-muted-foreground">
|
|
247
|
-
Drag the inner edge to resize. Disabled on mobile (< 768px) by
|
|
248
|
-
default — pass <code>resizableOnDesktopOnly={'{false}'}</code> to allow
|
|
249
|
-
on touch.
|
|
250
|
-
</p>
|
|
251
|
-
<Drawer direction="right">
|
|
252
|
-
<DrawerTrigger asChild>
|
|
253
|
-
<Button variant="outline">Open resizable drawer</Button>
|
|
254
|
-
</DrawerTrigger>
|
|
255
|
-
<DrawerContent
|
|
256
|
-
direction="right"
|
|
257
|
-
size="md"
|
|
258
|
-
resizable
|
|
259
|
-
minSize={320}
|
|
260
|
-
maxSize={900}
|
|
261
|
-
onSizeChange={setSize}
|
|
262
|
-
>
|
|
263
|
-
<DrawerHeader>
|
|
264
|
-
<DrawerTitle>Resizable</DrawerTitle>
|
|
265
|
-
<DrawerDescription>
|
|
266
|
-
Current width: {size != null ? `${Math.round(size)}px` : 'preset (480px)'}
|
|
267
|
-
</DrawerDescription>
|
|
268
|
-
</DrawerHeader>
|
|
269
|
-
<div className="p-4 text-sm">Drag the left edge to resize.</div>
|
|
270
|
-
<DrawerFooter>
|
|
271
|
-
<DrawerClose asChild>
|
|
272
|
-
<Button variant="outline">Close</Button>
|
|
273
|
-
</DrawerClose>
|
|
274
|
-
</DrawerFooter>
|
|
275
|
-
</DrawerContent>
|
|
276
|
-
</Drawer>
|
|
277
|
-
</div>
|
|
278
|
-
);
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
export const ResizablePersisted = () => {
|
|
282
|
-
const drawer = useDrawerSize('story-demo', { axis: 'width', min: 320, max: 900 });
|
|
283
|
-
return (
|
|
284
|
-
<div className="space-y-3">
|
|
285
|
-
<p className="text-sm text-muted-foreground">
|
|
286
|
-
Persistence is wired via the <code>useDrawerSize(key)</code> hook —
|
|
287
|
-
the drawer itself is just a controlled component. Reload the page and
|
|
288
|
-
reopen, the last width is restored from <code>localStorage</code>.
|
|
289
|
-
</p>
|
|
290
|
-
<div className="flex gap-2">
|
|
291
|
-
<Drawer direction="right">
|
|
292
|
-
<DrawerTrigger asChild>
|
|
293
|
-
<Button variant="outline">Open persisted drawer</Button>
|
|
294
|
-
</DrawerTrigger>
|
|
295
|
-
<DrawerContent
|
|
296
|
-
direction="right"
|
|
297
|
-
size="md"
|
|
298
|
-
resizable
|
|
299
|
-
minSize={320}
|
|
300
|
-
maxSize={900}
|
|
301
|
-
resizedSize={drawer.size}
|
|
302
|
-
onSizeChange={drawer.setSize}
|
|
303
|
-
>
|
|
304
|
-
<DrawerHeader>
|
|
305
|
-
<DrawerTitle>Resizable + persisted</DrawerTitle>
|
|
306
|
-
<DrawerDescription>
|
|
307
|
-
Stored in <code>djangocfg.ui.state</code>. Current:{' '}
|
|
308
|
-
{drawer.size != null ? `${Math.round(drawer.size)}px` : 'preset (480px)'}
|
|
309
|
-
</DrawerDescription>
|
|
310
|
-
</DrawerHeader>
|
|
311
|
-
<div className="p-4 text-sm">Drag the left edge to resize.</div>
|
|
312
|
-
<DrawerFooter>
|
|
313
|
-
<DrawerClose asChild>
|
|
314
|
-
<Button variant="outline">Close</Button>
|
|
315
|
-
</DrawerClose>
|
|
316
|
-
</DrawerFooter>
|
|
317
|
-
</DrawerContent>
|
|
318
|
-
</Drawer>
|
|
319
|
-
<Button variant="ghost" onClick={drawer.reset}>Reset stored size</Button>
|
|
320
|
-
</div>
|
|
321
|
-
</div>
|
|
322
|
-
);
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
export const NarrowViewport = () => (
|
|
326
|
-
<div className="space-y-3">
|
|
327
|
-
<p className="text-sm text-muted-foreground">
|
|
328
|
-
Resize the browser narrower than the size preset (e.g. < 480px for
|
|
329
|
-
<code> md</code>) to see <code>min(100vw, …)</code> clamp the drawer
|
|
330
|
-
to the viewport. This is the regression we now guard against.
|
|
331
|
-
</p>
|
|
332
|
-
<div
|
|
333
|
-
style={{ width: 360 }}
|
|
334
|
-
className="rounded border border-dashed p-4"
|
|
335
|
-
>
|
|
336
|
-
<Drawer direction="right">
|
|
337
|
-
<DrawerTrigger asChild>
|
|
338
|
-
<Button variant="outline">Open in 360px container</Button>
|
|
339
|
-
</DrawerTrigger>
|
|
340
|
-
<DrawerContent direction="right" size="md">
|
|
341
|
-
<DrawerHeader>
|
|
342
|
-
<DrawerTitle>Narrow viewport</DrawerTitle>
|
|
343
|
-
<DrawerDescription>
|
|
344
|
-
Drawer is portaled to the body — viewport width still applies.
|
|
345
|
-
</DrawerDescription>
|
|
346
|
-
</DrawerHeader>
|
|
347
|
-
<div className="p-4 text-sm">
|
|
348
|
-
min(100vw, 480px) keeps the drawer within bounds on tiny screens.
|
|
349
|
-
</div>
|
|
350
|
-
<DrawerFooter>
|
|
351
|
-
<DrawerClose asChild>
|
|
352
|
-
<Button variant="outline">Close</Button>
|
|
353
|
-
</DrawerClose>
|
|
354
|
-
</DrawerFooter>
|
|
355
|
-
</DrawerContent>
|
|
356
|
-
</Drawer>
|
|
357
|
-
</div>
|
|
358
|
-
</div>
|
|
359
|
-
);
|