appos 0.4.3-0 → 0.5.1-0
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/exports/api/index.d.mts +3 -3
- package/dist/exports/api/index.mjs +34 -9
- package/dist/exports/api/workflows/index.d.mts +2 -2
- package/dist/exports/api/workflows/index.mjs +2 -2
- package/dist/exports/{auth-By0xx0MI.d.mts → auth-BCOIpGDO.d.mts} +325 -214
- package/dist/exports/cli/index.d.mts +105 -106
- package/dist/exports/cli/index.mjs +87 -13
- package/dist/exports/{constants-BePPc_yF.mjs → constants-BicCnEiJ.mjs} +7 -1
- package/dist/exports/{index-Bpo5QE7k.d.mts → index-CiuTp085.d.mts} +580 -614
- package/dist/exports/{openapi-crG3j4xx.mjs → openapi-uisUTLq7.mjs} +45 -102
- package/dist/exports/{send-email-Bgcdjy-e.mjs → send-email-CXxlkfFL.mjs} +1 -1
- package/dist/exports/{server-BlNxgHUc.mjs → server-CA4aI0U6.mjs} +6 -2
- package/dist/exports/storybook/index.d.ts +40 -0
- package/dist/exports/storybook/index.js +43 -0
- package/dist/exports/tests/api.d.mts +2 -2
- package/dist/exports/tests/api.mjs +3 -3
- package/dist/exports/vite/index.d.mts +19 -3
- package/dist/exports/vite/index.mjs +82 -6
- package/dist/exports/web/index.d.ts +2247 -700
- package/dist/exports/web/index.js +2445 -754
- package/dist/exports/web/routes.d.mts +41 -43
- package/dist/exports/web/ssr.d.mts +2 -2
- package/package.json +48 -31
- package/src/storybook/.storybook/main.ts +119 -0
- package/src/storybook/.storybook/manager.ts +75 -0
- package/src/storybook/.storybook/preview.tsx +76 -0
- package/src/storybook/components/ColorGrid.tsx +324 -0
- package/src/storybook/components/IconGallery.tsx +268 -0
- package/src/storybook/components/SpacingScale.tsx +236 -0
- package/src/storybook/components/TypographyScale.tsx +277 -0
- package/src/storybook/components/index.ts +3 -0
- package/src/storybook/docs/Introduction.mdx +29 -0
- package/src/storybook/docs/foundations/Colors.mdx +27 -0
- package/src/storybook/docs/foundations/Icons.mdx +26 -0
- package/src/storybook/docs/foundations/Spacing.mdx +23 -0
- package/src/storybook/docs/foundations/Typography.mdx +39 -0
- package/src/storybook/index.ts +147 -0
- package/src/storybook/shims/void-elements.js +18 -0
- package/src/web/client/auth-paths.ts +148 -0
- package/src/web/client/auth.ts +218 -0
- package/src/web/client/i18n.d.ts +9 -0
- package/src/web/client/i18n.ts +127 -0
- package/src/web/client/react-router.ts +84 -0
- package/src/web/hooks/index.ts +1 -0
- package/src/web/hooks/use-mobile.ts +19 -0
- package/src/web/index.ts +42 -0
- package/src/web/lib/colors.ts +220 -0
- package/src/web/lib/utils.ts +52 -0
- package/src/web/routes/auth/_layout.tsx +5 -11
- package/src/web/routes.ts +101 -0
- package/src/web/server/context.ts +14 -0
- package/src/web/server/render.ts +11 -0
- package/src/web/ssr.ts +17 -0
- package/src/web/ui/accordion.stories.tsx +183 -0
- package/src/web/ui/accordion.tsx +134 -0
- package/src/web/ui/alert-dialog.stories.tsx +215 -0
- package/src/web/ui/alert-dialog.tsx +328 -0
- package/src/web/ui/alert.stories.tsx +224 -0
- package/src/web/ui/alert.tsx +136 -0
- package/src/web/ui/animated-check.stories.tsx +200 -0
- package/src/web/ui/animated-check.tsx +98 -0
- package/src/web/ui/aspect-ratio.stories.tsx +204 -0
- package/src/web/ui/aspect-ratio.tsx +36 -0
- package/src/web/ui/auth/__mocks__/auth-context.tsx +273 -0
- package/src/web/ui/auth/auth-card.stories.tsx +295 -0
- package/src/web/ui/auth/auth-card.tsx +124 -0
- package/src/web/ui/auth/auth-layout.stories.tsx +330 -0
- package/src/web/ui/auth/auth-layout.tsx +269 -0
- package/src/web/ui/auth/captcha-widget.stories.tsx +200 -0
- package/src/web/ui/auth/captcha-widget.tsx +197 -0
- package/src/web/ui/auth/context.tsx +87 -0
- package/src/web/ui/auth/email-input.stories.tsx +167 -0
- package/src/web/ui/auth/email-input.tsx +84 -0
- package/src/web/ui/auth/forms/email-otp-form.tsx +377 -0
- package/src/web/ui/auth/forms/forgot-password-form.tsx +240 -0
- package/src/web/ui/auth/forms/index.ts +40 -0
- package/src/web/ui/auth/forms/login-form.tsx +486 -0
- package/src/web/ui/auth/forms/phone-otp-form.tsx +388 -0
- package/src/web/ui/auth/forms/reset-password-form.tsx +331 -0
- package/src/web/ui/auth/forms/signup-form.tsx +499 -0
- package/src/web/ui/auth/forms/two-factor-form.tsx +410 -0
- package/src/web/ui/auth/forms/verify-email-form.tsx +373 -0
- package/src/web/ui/auth/hooks.ts +266 -0
- package/src/web/ui/auth/index.ts +31 -0
- package/src/web/ui/auth/magic-link-form.tsx +191 -0
- package/src/web/ui/auth/otp-input.stories.tsx +199 -0
- package/src/web/ui/auth/otp-input.tsx +157 -0
- package/src/web/ui/auth/passkey-button.stories.tsx +115 -0
- package/src/web/ui/auth/passkey-button.tsx +113 -0
- package/src/web/ui/auth/passkey-register-button.stories.tsx +109 -0
- package/src/web/ui/auth/passkey-register-button.tsx +106 -0
- package/src/web/ui/auth/password-input.stories.tsx +287 -0
- package/src/web/ui/auth/password-input.tsx +306 -0
- package/src/web/ui/auth/phone-input.stories.tsx +160 -0
- package/src/web/ui/auth/phone-input.tsx +89 -0
- package/src/web/ui/auth/social-buttons.stories.tsx +217 -0
- package/src/web/ui/auth/social-buttons.tsx +196 -0
- package/src/web/ui/auth/sso-button.stories.tsx +160 -0
- package/src/web/ui/auth/sso-button.tsx +108 -0
- package/src/web/ui/auth/trust-signals.stories.tsx +208 -0
- package/src/web/ui/auth/trust-signals.tsx +260 -0
- package/src/web/ui/avatar.stories.tsx +302 -0
- package/src/web/ui/avatar.tsx +189 -0
- package/src/web/ui/badge.stories.tsx +225 -0
- package/src/web/ui/badge.tsx +66 -0
- package/src/web/ui/brand.stories.tsx +266 -0
- package/src/web/ui/brand.tsx +162 -0
- package/src/web/ui/breadcrumb.stories.tsx +271 -0
- package/src/web/ui/breadcrumb.tsx +214 -0
- package/src/web/ui/button-group.stories.tsx +251 -0
- package/src/web/ui/button-group.tsx +87 -0
- package/src/web/ui/button.stories.tsx +264 -0
- package/src/web/ui/button.tsx +120 -0
- package/src/web/ui/calendar.stories.tsx +235 -0
- package/src/web/ui/calendar.tsx +221 -0
- package/src/web/ui/card.stories.tsx +262 -0
- package/src/web/ui/card.tsx +199 -0
- package/src/web/ui/carousel.stories.tsx +244 -0
- package/src/web/ui/carousel.tsx +241 -0
- package/src/web/ui/chart.stories.tsx +833 -0
- package/src/web/ui/chart.tsx +390 -0
- package/src/web/ui/checkbox.stories.tsx +208 -0
- package/src/web/ui/checkbox.tsx +39 -0
- package/src/web/ui/collapsible.stories.tsx +239 -0
- package/src/web/ui/collapsible.tsx +21 -0
- package/src/web/ui/command.stories.tsx +291 -0
- package/src/web/ui/command.tsx +189 -0
- package/src/web/ui/context-menu.stories.tsx +255 -0
- package/src/web/ui/context-menu.tsx +263 -0
- package/src/web/ui/dialog.stories.tsx +263 -0
- package/src/web/ui/dialog.tsx +273 -0
- package/src/web/ui/drawer.stories.tsx +299 -0
- package/src/web/ui/drawer.tsx +130 -0
- package/src/web/ui/dropdown-menu.stories.tsx +320 -0
- package/src/web/ui/dropdown-menu.tsx +263 -0
- package/src/web/ui/empty.stories.tsx +204 -0
- package/src/web/ui/empty.tsx +101 -0
- package/src/web/ui/error-page.stories.tsx +181 -0
- package/src/web/ui/error-page.tsx +136 -0
- package/src/web/ui/field.stories.tsx +364 -0
- package/src/web/ui/field.tsx +252 -0
- package/src/web/ui/globals.css +3 -0
- package/src/web/ui/hover-card.stories.tsx +261 -0
- package/src/web/ui/hover-card.tsx +50 -0
- package/src/web/ui/index.ts +55 -0
- package/src/web/ui/input-group.stories.tsx +290 -0
- package/src/web/ui/input-group.tsx +157 -0
- package/src/web/ui/input-otp.stories.tsx +235 -0
- package/src/web/ui/input-otp.tsx +86 -0
- package/src/web/ui/input.stories.tsx +205 -0
- package/src/web/ui/input.tsx +30 -0
- package/src/web/ui/item.stories.tsx +348 -0
- package/src/web/ui/item.tsx +200 -0
- package/src/web/ui/kbd.stories.tsx +236 -0
- package/src/web/ui/kbd.tsx +27 -0
- package/src/web/ui/label.stories.tsx +180 -0
- package/src/web/ui/label.tsx +32 -0
- package/src/web/ui/locales/en/ui.json +13 -30
- package/src/web/ui/locales/zh-CN/ui.json +17 -34
- package/src/web/ui/locales/zh-TW/ui.json +17 -34
- package/src/web/ui/menubar.stories.tsx +385 -0
- package/src/web/ui/menubar.tsx +273 -0
- package/src/web/ui/navigation-menu.stories.tsx +361 -0
- package/src/web/ui/navigation-menu.tsx +168 -0
- package/src/web/ui/pagination.stories.tsx +312 -0
- package/src/web/ui/pagination.tsx +221 -0
- package/src/web/ui/popover.stories.tsx +315 -0
- package/src/web/ui/popover.tsx +89 -0
- package/src/web/ui/progress.stories.tsx +239 -0
- package/src/web/ui/progress.tsx +128 -0
- package/src/web/ui/radio-group.stories.tsx +315 -0
- package/src/web/ui/radio-group.tsx +38 -0
- package/src/web/ui/resizable.stories.tsx +304 -0
- package/src/web/ui/resizable.tsx +53 -0
- package/src/web/ui/scroll-area.stories.tsx +276 -0
- package/src/web/ui/scroll-area.tsx +53 -0
- package/src/web/ui/select.stories.tsx +314 -0
- package/src/web/ui/select.tsx +312 -0
- package/src/web/ui/separator.stories.tsx +246 -0
- package/src/web/ui/separator.tsx +36 -0
- package/src/web/ui/sheet.stories.tsx +417 -0
- package/src/web/ui/sheet.tsx +133 -0
- package/src/web/ui/sidebar.stories.tsx +402 -0
- package/src/web/ui/sidebar.tsx +723 -0
- package/src/web/ui/skeleton.stories.tsx +235 -0
- package/src/web/ui/skeleton.tsx +26 -0
- package/src/web/ui/slider.stories.tsx +294 -0
- package/src/web/ui/slider.tsx +75 -0
- package/src/web/ui/sonner.stories.tsx +279 -0
- package/src/web/ui/sonner.tsx +46 -0
- package/src/web/ui/spinner.stories.tsx +204 -0
- package/src/web/ui/spinner.tsx +28 -0
- package/src/web/ui/switch.stories.tsx +285 -0
- package/src/web/ui/switch.tsx +43 -0
- package/src/web/ui/table.stories.tsx +362 -0
- package/src/web/ui/table.tsx +115 -0
- package/src/web/ui/tabs.stories.tsx +401 -0
- package/src/web/ui/tabs.tsx +136 -0
- package/src/web/ui/textarea.stories.tsx +272 -0
- package/src/web/ui/textarea.tsx +28 -0
- package/src/web/ui/toggle-group.stories.tsx +334 -0
- package/src/web/ui/toggle-group.tsx +88 -0
- package/src/web/ui/toggle.stories.tsx +264 -0
- package/src/web/ui/toggle.tsx +57 -0
- package/src/web/ui/tooltip.stories.tsx +342 -0
- package/src/web/ui/tooltip.tsx +116 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Dialog,
|
|
5
|
+
DialogClose,
|
|
6
|
+
DialogContent,
|
|
7
|
+
DialogDescription,
|
|
8
|
+
DialogFooter,
|
|
9
|
+
DialogHeader,
|
|
10
|
+
DialogTitle,
|
|
11
|
+
DialogTrigger,
|
|
12
|
+
Input,
|
|
13
|
+
Label,
|
|
14
|
+
} from "appos/web";
|
|
15
|
+
import { expect, userEvent, within } from "storybook/test";
|
|
16
|
+
|
|
17
|
+
const meta = {
|
|
18
|
+
title: "Base/Dialog",
|
|
19
|
+
component: Dialog,
|
|
20
|
+
tags: ["autodocs"],
|
|
21
|
+
parameters: {
|
|
22
|
+
layout: "centered",
|
|
23
|
+
docs: {
|
|
24
|
+
description: {
|
|
25
|
+
component:
|
|
26
|
+
"A modal dialog component for displaying content that requires user attention. Supports headers, footers, forms, and customizable close behavior.",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
} satisfies Meta<typeof Dialog>;
|
|
31
|
+
|
|
32
|
+
export default meta;
|
|
33
|
+
type Story = StoryObj<typeof meta>;
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {
|
|
36
|
+
render: () => (
|
|
37
|
+
<Dialog>
|
|
38
|
+
<DialogTrigger render={<Button variant="outline" />}>
|
|
39
|
+
Edit Profile
|
|
40
|
+
</DialogTrigger>
|
|
41
|
+
<DialogContent>
|
|
42
|
+
<DialogHeader>
|
|
43
|
+
<DialogTitle>Edit Profile</DialogTitle>
|
|
44
|
+
<DialogDescription>
|
|
45
|
+
Make changes to your profile here. Click save when you're done.
|
|
46
|
+
</DialogDescription>
|
|
47
|
+
</DialogHeader>
|
|
48
|
+
<div className="grid gap-4 py-4">
|
|
49
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
50
|
+
<Label htmlFor="name" className="text-right">
|
|
51
|
+
Name
|
|
52
|
+
</Label>
|
|
53
|
+
<Input id="name" defaultValue="John Doe" className="col-span-3" />
|
|
54
|
+
</div>
|
|
55
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
56
|
+
<Label htmlFor="username" className="text-right">
|
|
57
|
+
Username
|
|
58
|
+
</Label>
|
|
59
|
+
<Input
|
|
60
|
+
id="username"
|
|
61
|
+
defaultValue="@johndoe"
|
|
62
|
+
className="col-span-3"
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
<DialogFooter>
|
|
67
|
+
<Button type="submit">Save changes</Button>
|
|
68
|
+
</DialogFooter>
|
|
69
|
+
</DialogContent>
|
|
70
|
+
</Dialog>
|
|
71
|
+
),
|
|
72
|
+
parameters: {
|
|
73
|
+
docs: {
|
|
74
|
+
description: {
|
|
75
|
+
story:
|
|
76
|
+
"Default dialog with a form. Includes header, content area, and footer with actions.",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
play: async ({ canvasElement }) => {
|
|
81
|
+
const canvas = within(canvasElement);
|
|
82
|
+
const trigger = canvas.getByRole("button", { name: /edit profile/i });
|
|
83
|
+
await userEvent.click(trigger);
|
|
84
|
+
await expect(
|
|
85
|
+
await within(document.body).findByRole("dialog"),
|
|
86
|
+
).toBeInTheDocument();
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const WithCloseButton: Story = {
|
|
91
|
+
render: () => (
|
|
92
|
+
<Dialog>
|
|
93
|
+
<DialogTrigger render={<Button variant="outline" />}>
|
|
94
|
+
Open Dialog
|
|
95
|
+
</DialogTrigger>
|
|
96
|
+
<DialogContent showCloseButton>
|
|
97
|
+
<DialogHeader>
|
|
98
|
+
<DialogTitle>Dialog with Close Button</DialogTitle>
|
|
99
|
+
<DialogDescription>
|
|
100
|
+
This dialog has a close button in the top-right corner.
|
|
101
|
+
</DialogDescription>
|
|
102
|
+
</DialogHeader>
|
|
103
|
+
<div className="py-4">
|
|
104
|
+
<p>Click the X button or press Escape to close this dialog.</p>
|
|
105
|
+
</div>
|
|
106
|
+
</DialogContent>
|
|
107
|
+
</Dialog>
|
|
108
|
+
),
|
|
109
|
+
parameters: {
|
|
110
|
+
docs: {
|
|
111
|
+
description: {
|
|
112
|
+
story:
|
|
113
|
+
"Dialog with an explicit close button. Use showCloseButton prop on DialogContent.",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const WithFooterCloseButton: Story = {
|
|
120
|
+
render: () => (
|
|
121
|
+
<Dialog>
|
|
122
|
+
<DialogTrigger render={<Button variant="outline" />}>
|
|
123
|
+
View Details
|
|
124
|
+
</DialogTrigger>
|
|
125
|
+
<DialogContent>
|
|
126
|
+
<DialogHeader>
|
|
127
|
+
<DialogTitle>Order Details</DialogTitle>
|
|
128
|
+
<DialogDescription>
|
|
129
|
+
View the details of your recent order.
|
|
130
|
+
</DialogDescription>
|
|
131
|
+
</DialogHeader>
|
|
132
|
+
<div className="py-4">
|
|
133
|
+
<dl className="space-y-2 text-sm">
|
|
134
|
+
<div className="flex justify-between">
|
|
135
|
+
<dt className="text-muted-foreground">Order ID</dt>
|
|
136
|
+
<dd>#12345</dd>
|
|
137
|
+
</div>
|
|
138
|
+
<div className="flex justify-between">
|
|
139
|
+
<dt className="text-muted-foreground">Date</dt>
|
|
140
|
+
<dd>Jan 15, 2025</dd>
|
|
141
|
+
</div>
|
|
142
|
+
<div className="flex justify-between">
|
|
143
|
+
<dt className="text-muted-foreground">Total</dt>
|
|
144
|
+
<dd>$99.99</dd>
|
|
145
|
+
</div>
|
|
146
|
+
</dl>
|
|
147
|
+
</div>
|
|
148
|
+
<DialogFooter showCloseButton />
|
|
149
|
+
</DialogContent>
|
|
150
|
+
</Dialog>
|
|
151
|
+
),
|
|
152
|
+
parameters: {
|
|
153
|
+
docs: {
|
|
154
|
+
description: {
|
|
155
|
+
story:
|
|
156
|
+
"Dialog with a close button in the footer. Use showCloseButton prop on DialogFooter.",
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export const SimpleAlert: Story = {
|
|
163
|
+
render: () => (
|
|
164
|
+
<Dialog>
|
|
165
|
+
<DialogTrigger render={<Button variant="outline" />}>
|
|
166
|
+
Show Alert
|
|
167
|
+
</DialogTrigger>
|
|
168
|
+
<DialogContent className="sm:max-w-md">
|
|
169
|
+
<DialogHeader>
|
|
170
|
+
<DialogTitle>Are you sure?</DialogTitle>
|
|
171
|
+
<DialogDescription>This action cannot be undone.</DialogDescription>
|
|
172
|
+
</DialogHeader>
|
|
173
|
+
<DialogFooter className="sm:justify-between">
|
|
174
|
+
<DialogClose render={<Button variant="outline" />}>
|
|
175
|
+
Cancel
|
|
176
|
+
</DialogClose>
|
|
177
|
+
<Button variant="destructive">Delete</Button>
|
|
178
|
+
</DialogFooter>
|
|
179
|
+
</DialogContent>
|
|
180
|
+
</Dialog>
|
|
181
|
+
),
|
|
182
|
+
parameters: {
|
|
183
|
+
docs: {
|
|
184
|
+
description: {
|
|
185
|
+
story:
|
|
186
|
+
"Simple alert-style dialog for confirmations. Use DialogClose for cancel actions.",
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export const CustomWidth: Story = {
|
|
193
|
+
render: () => (
|
|
194
|
+
<Dialog>
|
|
195
|
+
<DialogTrigger render={<Button variant="outline" />}>
|
|
196
|
+
Wide Dialog
|
|
197
|
+
</DialogTrigger>
|
|
198
|
+
<DialogContent className="sm:max-w-2xl">
|
|
199
|
+
<DialogHeader>
|
|
200
|
+
<DialogTitle>Wide Dialog</DialogTitle>
|
|
201
|
+
<DialogDescription>
|
|
202
|
+
This dialog has a custom max-width for larger content.
|
|
203
|
+
</DialogDescription>
|
|
204
|
+
</DialogHeader>
|
|
205
|
+
<div className="py-4">
|
|
206
|
+
<p className="text-muted-foreground text-sm">
|
|
207
|
+
Use Tailwind classes like sm:max-w-2xl to customize the dialog
|
|
208
|
+
width. The default is sm:max-w-md.
|
|
209
|
+
</p>
|
|
210
|
+
</div>
|
|
211
|
+
</DialogContent>
|
|
212
|
+
</Dialog>
|
|
213
|
+
),
|
|
214
|
+
parameters: {
|
|
215
|
+
docs: {
|
|
216
|
+
description: {
|
|
217
|
+
story:
|
|
218
|
+
"Dialog with custom width. Override max-width using Tailwind classes.",
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const ScrollableContent: Story = {
|
|
225
|
+
render: () => (
|
|
226
|
+
<Dialog>
|
|
227
|
+
<DialogTrigger render={<Button variant="outline" />}>
|
|
228
|
+
Terms of Service
|
|
229
|
+
</DialogTrigger>
|
|
230
|
+
<DialogContent className="max-h-[80vh] overflow-y-auto">
|
|
231
|
+
<DialogHeader>
|
|
232
|
+
<DialogTitle>Terms of Service</DialogTitle>
|
|
233
|
+
<DialogDescription>
|
|
234
|
+
Please read and accept our terms of service.
|
|
235
|
+
</DialogDescription>
|
|
236
|
+
</DialogHeader>
|
|
237
|
+
<div className="py-4 text-sm">
|
|
238
|
+
{Array.from({ length: 10 }).map((_, i) => (
|
|
239
|
+
<p key={i} className="mb-4">
|
|
240
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
|
|
241
|
+
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
|
|
242
|
+
enim ad minim veniam, quis nostrud exercitation ullamco laboris
|
|
243
|
+
nisi ut aliquip ex ea commodo consequat.
|
|
244
|
+
</p>
|
|
245
|
+
))}
|
|
246
|
+
</div>
|
|
247
|
+
<DialogFooter>
|
|
248
|
+
<DialogClose render={<Button variant="outline" />}>
|
|
249
|
+
Decline
|
|
250
|
+
</DialogClose>
|
|
251
|
+
<Button>Accept</Button>
|
|
252
|
+
</DialogFooter>
|
|
253
|
+
</DialogContent>
|
|
254
|
+
</Dialog>
|
|
255
|
+
),
|
|
256
|
+
parameters: {
|
|
257
|
+
docs: {
|
|
258
|
+
description: {
|
|
259
|
+
story: "Dialog with scrollable content for long text or lists.",
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
4
|
+
import { XIcon } from "lucide-react";
|
|
5
|
+
import type * as React from "react";
|
|
6
|
+
import { cn } from "#src/web/lib/utils.ts";
|
|
7
|
+
import { Button } from "#src/web/ui/button.tsx";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A modal window that appears above the page content.
|
|
11
|
+
*
|
|
12
|
+
* Use for focused tasks like forms, confirmations, or displaying detailed
|
|
13
|
+
* information. Traps focus and prevents interaction with the background.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <Dialog>
|
|
18
|
+
* <DialogTrigger render={<Button />}>Open Dialog</DialogTrigger>
|
|
19
|
+
* <DialogContent>
|
|
20
|
+
* <DialogHeader>
|
|
21
|
+
* <DialogTitle>Edit Profile</DialogTitle>
|
|
22
|
+
* <DialogDescription>Make changes to your profile.</DialogDescription>
|
|
23
|
+
* </DialogHeader>
|
|
24
|
+
* <DialogFooter>
|
|
25
|
+
* <Button>Save changes</Button>
|
|
26
|
+
* </DialogFooter>
|
|
27
|
+
* </DialogContent>
|
|
28
|
+
* </Dialog>
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
function Dialog({ ...props }: DialogPrimitive.Root.Props) {
|
|
32
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The button that opens the dialog.
|
|
37
|
+
*
|
|
38
|
+
* Use the `render` prop to customize the trigger element while maintaining
|
|
39
|
+
* proper accessibility attributes.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* <DialogTrigger render={<Button />}>Open</DialogTrigger>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
|
|
47
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Portals the dialog content to the end of the document body.
|
|
52
|
+
*
|
|
53
|
+
* Used internally by DialogContent. Ensures the dialog renders above
|
|
54
|
+
* other content regardless of DOM position.
|
|
55
|
+
*/
|
|
56
|
+
function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
|
|
57
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A button that closes the dialog when clicked.
|
|
62
|
+
*
|
|
63
|
+
* Can be placed anywhere within the dialog content.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```tsx
|
|
67
|
+
* <DialogClose render={<Button variant="outline" />}>Cancel</DialogClose>
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
|
|
71
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The backdrop overlay behind the dialog.
|
|
76
|
+
*
|
|
77
|
+
* Dims the background and prevents interaction with the page. Includes
|
|
78
|
+
* blur effect on supported browsers. Used internally by DialogContent.
|
|
79
|
+
*/
|
|
80
|
+
function DialogOverlay({
|
|
81
|
+
className,
|
|
82
|
+
...props
|
|
83
|
+
}: DialogPrimitive.Backdrop.Props) {
|
|
84
|
+
return (
|
|
85
|
+
<DialogPrimitive.Backdrop
|
|
86
|
+
data-slot="dialog-overlay"
|
|
87
|
+
className={cn(
|
|
88
|
+
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50",
|
|
89
|
+
className,
|
|
90
|
+
)}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The container for the dialog content.
|
|
98
|
+
*
|
|
99
|
+
* Centers the dialog on screen with smooth open/close animations. Includes
|
|
100
|
+
* the portal and overlay automatically. Optionally shows a close button.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```tsx
|
|
104
|
+
* <DialogContent>
|
|
105
|
+
* <DialogHeader>...</DialogHeader>
|
|
106
|
+
* <DialogFooter>...</DialogFooter>
|
|
107
|
+
* </DialogContent>
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
function DialogContent({
|
|
111
|
+
className,
|
|
112
|
+
children,
|
|
113
|
+
showCloseButton = true,
|
|
114
|
+
...props
|
|
115
|
+
}: DialogPrimitive.Popup.Props & {
|
|
116
|
+
showCloseButton?: boolean;
|
|
117
|
+
}) {
|
|
118
|
+
return (
|
|
119
|
+
<DialogPortal>
|
|
120
|
+
<DialogOverlay />
|
|
121
|
+
<DialogPrimitive.Popup
|
|
122
|
+
data-slot="dialog-content"
|
|
123
|
+
className={cn(
|
|
124
|
+
"bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-6 rounded-xl p-6 text-sm ring-1 duration-100 sm:max-w-md fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none",
|
|
125
|
+
className,
|
|
126
|
+
)}
|
|
127
|
+
{...props}
|
|
128
|
+
>
|
|
129
|
+
{children}
|
|
130
|
+
{showCloseButton && (
|
|
131
|
+
<DialogPrimitive.Close
|
|
132
|
+
data-slot="dialog-close"
|
|
133
|
+
render={
|
|
134
|
+
<Button
|
|
135
|
+
variant="ghost"
|
|
136
|
+
className="absolute top-4 right-4"
|
|
137
|
+
size="icon-sm"
|
|
138
|
+
/>
|
|
139
|
+
}
|
|
140
|
+
>
|
|
141
|
+
<XIcon />
|
|
142
|
+
<span className="sr-only">Close</span>
|
|
143
|
+
</DialogPrimitive.Close>
|
|
144
|
+
)}
|
|
145
|
+
</DialogPrimitive.Popup>
|
|
146
|
+
</DialogPortal>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The header section containing the dialog title and description.
|
|
152
|
+
*
|
|
153
|
+
* Provides consistent spacing and layout for dialog headers.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```tsx
|
|
157
|
+
* <DialogHeader>
|
|
158
|
+
* <DialogTitle>Edit Settings</DialogTitle>
|
|
159
|
+
* <DialogDescription>Configure your preferences.</DialogDescription>
|
|
160
|
+
* </DialogHeader>
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
164
|
+
return (
|
|
165
|
+
<div
|
|
166
|
+
data-slot="dialog-header"
|
|
167
|
+
className={cn("gap-2 flex flex-col", className)}
|
|
168
|
+
{...props}
|
|
169
|
+
/>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* The footer section containing dialog action buttons.
|
|
175
|
+
*
|
|
176
|
+
* Arranges buttons in a responsive layout with proper spacing.
|
|
177
|
+
* Optionally includes a close button.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```tsx
|
|
181
|
+
* <DialogFooter>
|
|
182
|
+
* <Button variant="outline">Cancel</Button>
|
|
183
|
+
* <Button>Save</Button>
|
|
184
|
+
* </DialogFooter>
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
function DialogFooter({
|
|
188
|
+
className,
|
|
189
|
+
showCloseButton = false,
|
|
190
|
+
children,
|
|
191
|
+
...props
|
|
192
|
+
}: React.ComponentProps<"div"> & {
|
|
193
|
+
showCloseButton?: boolean;
|
|
194
|
+
}) {
|
|
195
|
+
return (
|
|
196
|
+
<div
|
|
197
|
+
data-slot="dialog-footer"
|
|
198
|
+
className={cn(
|
|
199
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
200
|
+
className,
|
|
201
|
+
)}
|
|
202
|
+
{...props}
|
|
203
|
+
>
|
|
204
|
+
{children}
|
|
205
|
+
{showCloseButton && (
|
|
206
|
+
<DialogPrimitive.Close render={<Button variant="outline" />}>
|
|
207
|
+
Close
|
|
208
|
+
</DialogPrimitive.Close>
|
|
209
|
+
)}
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* The title text for the dialog.
|
|
216
|
+
*
|
|
217
|
+
* Displayed prominently and announced by screen readers when the dialog opens.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```tsx
|
|
221
|
+
* <DialogTitle>Confirm Action</DialogTitle>
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
|
|
225
|
+
return (
|
|
226
|
+
<DialogPrimitive.Title
|
|
227
|
+
data-slot="dialog-title"
|
|
228
|
+
className={cn("leading-none font-medium", className)}
|
|
229
|
+
{...props}
|
|
230
|
+
/>
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* The descriptive text explaining the dialog purpose.
|
|
236
|
+
*
|
|
237
|
+
* Provides context about the action or content within the dialog.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```tsx
|
|
241
|
+
* <DialogDescription>
|
|
242
|
+
* This action cannot be undone. Please confirm your choice.
|
|
243
|
+
* </DialogDescription>
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
function DialogDescription({
|
|
247
|
+
className,
|
|
248
|
+
...props
|
|
249
|
+
}: DialogPrimitive.Description.Props) {
|
|
250
|
+
return (
|
|
251
|
+
<DialogPrimitive.Description
|
|
252
|
+
data-slot="dialog-description"
|
|
253
|
+
className={cn(
|
|
254
|
+
"text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3",
|
|
255
|
+
className,
|
|
256
|
+
)}
|
|
257
|
+
{...props}
|
|
258
|
+
/>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export {
|
|
263
|
+
Dialog,
|
|
264
|
+
DialogClose,
|
|
265
|
+
DialogContent,
|
|
266
|
+
DialogDescription,
|
|
267
|
+
DialogFooter,
|
|
268
|
+
DialogHeader,
|
|
269
|
+
DialogOverlay,
|
|
270
|
+
DialogPortal,
|
|
271
|
+
DialogTitle,
|
|
272
|
+
DialogTrigger,
|
|
273
|
+
};
|