@adamosuiteservices/ui 2.11.14 → 2.11.16
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/colors.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/themes.css +1 -1
- package/docs/AI-GUIDE.md +321 -321
- package/docs/components/layout/sidebar.md +399 -399
- package/docs/components/layout/toaster.md +436 -436
- package/docs/components/ui/accordion-rounded.md +584 -584
- package/docs/components/ui/accordion.md +269 -269
- package/docs/components/ui/button-group.md +984 -984
- package/docs/components/ui/button.md +1137 -1137
- package/docs/components/ui/calendar.md +1159 -1159
- package/docs/components/ui/card.md +1455 -1455
- package/docs/components/ui/checkbox.md +292 -292
- package/docs/components/ui/collapsible.md +323 -323
- package/docs/components/ui/command.md +454 -454
- package/docs/components/ui/context-menu.md +540 -540
- package/docs/components/ui/dialog.md +628 -628
- package/docs/components/ui/dropdown-menu.md +709 -709
- package/docs/components/ui/field.md +706 -706
- package/docs/components/ui/hover-card.md +446 -446
- package/docs/components/ui/input.md +362 -362
- package/docs/components/ui/kbd.md +434 -434
- package/docs/components/ui/label.md +359 -359
- package/docs/components/ui/pagination.md +650 -650
- package/docs/components/ui/popover.md +536 -536
- package/docs/components/ui/progress.md +182 -182
- package/docs/components/ui/radio-group.md +311 -311
- package/docs/components/ui/select.md +352 -352
- package/docs/components/ui/separator.md +214 -214
- package/docs/components/ui/sheet.md +142 -142
- package/docs/components/ui/skeleton.md +140 -140
- package/docs/components/ui/slider.md +341 -341
- package/docs/components/ui/spinner.md +170 -170
- package/docs/components/ui/switch.md +408 -408
- package/docs/components/ui/tabs-underline.md +106 -106
- package/docs/components/ui/tabs.md +122 -122
- package/docs/components/ui/textarea.md +243 -243
- package/docs/components/ui/toggle.md +237 -237
- package/docs/components/ui/tooltip.md +317 -317
- package/docs/components/ui/typography.md +280 -280
- package/package.json +1 -1
|
@@ -1,628 +1,628 @@
|
|
|
1
|
-
# Dialog
|
|
2
|
-
|
|
3
|
-
Ventana modal centrada sobre overlay semi-transparente, basada en Radix UI. Soporta formularios, confirmaciones, información, y acciones. Útil para capturar atención del usuario en tareas críticas.
|
|
4
|
-
|
|
5
|
-
## Importación
|
|
6
|
-
|
|
7
|
-
```tsx
|
|
8
|
-
import {
|
|
9
|
-
Dialog,
|
|
10
|
-
DialogTrigger,
|
|
11
|
-
DialogContent,
|
|
12
|
-
DialogHeader,
|
|
13
|
-
DialogTitle,
|
|
14
|
-
DialogDescription,
|
|
15
|
-
DialogBody,
|
|
16
|
-
DialogFooter,
|
|
17
|
-
DialogClose,
|
|
18
|
-
DialogOverlay,
|
|
19
|
-
DialogPortal,
|
|
20
|
-
} from "@adamosuiteservices/ui/dialog";
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Anatomía
|
|
24
|
-
|
|
25
|
-
```tsx
|
|
26
|
-
<Dialog>
|
|
27
|
-
<DialogTrigger>Open Dialog</DialogTrigger>
|
|
28
|
-
<DialogContent>
|
|
29
|
-
<DialogHeader>
|
|
30
|
-
<DialogTitle>Title</DialogTitle>
|
|
31
|
-
<DialogDescription>Description text</DialogDescription>
|
|
32
|
-
</DialogHeader>
|
|
33
|
-
<DialogBody>{/* Main content */}</DialogBody>
|
|
34
|
-
<DialogFooter>
|
|
35
|
-
<DialogClose asChild>
|
|
36
|
-
<Button variant="outline">Cancel</Button>
|
|
37
|
-
</DialogClose>
|
|
38
|
-
<Button>Confirm</Button>
|
|
39
|
-
</DialogFooter>
|
|
40
|
-
</DialogContent>
|
|
41
|
-
</Dialog>
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Componentes**: 10 (Dialog, Trigger, Content, Header, Title, Description, Body, Footer, Close, Overlay, Portal)
|
|
45
|
-
|
|
46
|
-
## Props Principales
|
|
47
|
-
|
|
48
|
-
### Dialog (Root)
|
|
49
|
-
|
|
50
|
-
| Prop | Tipo | Default | Descripción |
|
|
51
|
-
| -------------- | ------------------------- | ------- | ----------------------------------------- |
|
|
52
|
-
| `open` | `boolean` | - | Estado controlado del dialog |
|
|
53
|
-
| `onOpenChange` | `(open: boolean) => void` | - | Callback cuando cambia estado |
|
|
54
|
-
| `defaultOpen` | `boolean` | `false` | Estado inicial no controlado |
|
|
55
|
-
| `modal` | `boolean` | `true` | Bloquea interacción con contenido externo |
|
|
56
|
-
|
|
57
|
-
### DialogTrigger
|
|
58
|
-
|
|
59
|
-
| Prop | Tipo | Descripción |
|
|
60
|
-
| ----------- | --------- | -------------------------------------------------- |
|
|
61
|
-
| `asChild` | `boolean` | Pasa props al child en lugar de renderizar wrapper |
|
|
62
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
63
|
-
|
|
64
|
-
### DialogContent
|
|
65
|
-
|
|
66
|
-
| Prop | Tipo | Default | Descripción |
|
|
67
|
-
| ---------------------- | ----------------- | ------- | ------------------------------------------------------- |
|
|
68
|
-
| `showCloseButton` | `boolean` | `true` | Muestra botón X en esquina superior derecha |
|
|
69
|
-
| `theme` | `Theme` | - | Tema personalizado (default, dark, pay, sign, risk, id) |
|
|
70
|
-
| `className` | `string` | - | Clases CSS adicionales |
|
|
71
|
-
| `onEscapeKeyDown` | `(event) => void` | - | Callback al presionar Escape |
|
|
72
|
-
| `onPointerDownOutside` | `(event) => void` | - | Callback al hacer clic fuera |
|
|
73
|
-
| `onInteractOutside` | `(event) => void` | - | Callback al interactuar fuera |
|
|
74
|
-
|
|
75
|
-
**Estilos default**: `max-w-lg`, `max-w-[calc(100%-2rem)]` en mobile, centrado, `rounded-lg`, `p-6`, `shadow-lg`
|
|
76
|
-
|
|
77
|
-
### DialogTitle
|
|
78
|
-
|
|
79
|
-
| Prop | Tipo | Descripción |
|
|
80
|
-
| ----------- | -------- | ---------------------- |
|
|
81
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
82
|
-
|
|
83
|
-
**Estilos**: `text-lg`, `font-semibold`, `leading-none`
|
|
84
|
-
|
|
85
|
-
### DialogDescription
|
|
86
|
-
|
|
87
|
-
| Prop | Tipo | Descripción |
|
|
88
|
-
| ----------- | -------- | ---------------------- |
|
|
89
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
90
|
-
|
|
91
|
-
**Estilos**: `text-sm`, `text-muted-foreground`
|
|
92
|
-
|
|
93
|
-
### DialogBody
|
|
94
|
-
|
|
95
|
-
| Prop | Tipo | Descripción |
|
|
96
|
-
| ----------- | -------- | ---------------------- |
|
|
97
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
98
|
-
|
|
99
|
-
**Estilos**: `mt-2 mb-6`
|
|
100
|
-
**Propósito**: Contenedor para el contenido principal del dialog entre el header y footer. Proporciona espaciado vertical consistente.
|
|
101
|
-
|
|
102
|
-
### DialogHeader
|
|
103
|
-
|
|
104
|
-
| Prop | Tipo | Descripción |
|
|
105
|
-
| ----------- | -------- | ---------------------- |
|
|
106
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
107
|
-
|
|
108
|
-
**Estilos**: `flex flex-col gap-2`, `text-center` en mobile, `sm:text-left`
|
|
109
|
-
|
|
110
|
-
### DialogFooter
|
|
111
|
-
|
|
112
|
-
| Prop | Tipo | Descripción |
|
|
113
|
-
| ----------- | -------- | ---------------------- |
|
|
114
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
115
|
-
|
|
116
|
-
**Estilos**: `flex-col-reverse` en mobile, `sm:flex-row sm:justify-end`, `gap-2`
|
|
117
|
-
|
|
118
|
-
### DialogClose
|
|
119
|
-
|
|
120
|
-
| Prop | Tipo | Descripción |
|
|
121
|
-
| ----------- | --------- | ------------------------------------------------- |
|
|
122
|
-
| `asChild` | `boolean` | Pasa props al child en lugar de renderizar button |
|
|
123
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
124
|
-
|
|
125
|
-
## Patrones de Uso
|
|
126
|
-
|
|
127
|
-
### Básico
|
|
128
|
-
|
|
129
|
-
```tsx
|
|
130
|
-
<Dialog>
|
|
131
|
-
<DialogTrigger>Open</DialogTrigger>
|
|
132
|
-
<DialogContent>
|
|
133
|
-
<DialogHeader>
|
|
134
|
-
<DialogTitle>Are you absolutely sure?</DialogTitle>
|
|
135
|
-
<DialogDescription>
|
|
136
|
-
This action cannot be undone. This will permanently delete your account.
|
|
137
|
-
</DialogDescription>
|
|
138
|
-
</DialogHeader>
|
|
139
|
-
</DialogContent>
|
|
140
|
-
</Dialog>
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Con Trigger Custom (asChild)
|
|
144
|
-
|
|
145
|
-
```tsx
|
|
146
|
-
<Dialog>
|
|
147
|
-
<DialogTrigger asChild>
|
|
148
|
-
<Button variant="outline">Edit Profile</Button>
|
|
149
|
-
</DialogTrigger>
|
|
150
|
-
<DialogContent>
|
|
151
|
-
<DialogHeader>
|
|
152
|
-
<DialogTitle>Edit Profile</DialogTitle>
|
|
153
|
-
<DialogDescription>Make changes to your profile here.</DialogDescription>
|
|
154
|
-
</DialogHeader>
|
|
155
|
-
</DialogContent>
|
|
156
|
-
</Dialog>
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### Formulario de Edición
|
|
160
|
-
|
|
161
|
-
```tsx
|
|
162
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
163
|
-
import { Input } from "@adamosuiteservices/ui/input";
|
|
164
|
-
import { Label } from "@adamosuiteservices/ui/label";
|
|
165
|
-
|
|
166
|
-
<Dialog>
|
|
167
|
-
<DialogTrigger asChild>
|
|
168
|
-
<Button variant="outline">Edit Profile</Button>
|
|
169
|
-
</DialogTrigger>
|
|
170
|
-
<DialogContent className="sm:max-w-[425px]">
|
|
171
|
-
<DialogHeader>
|
|
172
|
-
<DialogTitle>Edit profile</DialogTitle>
|
|
173
|
-
<DialogDescription>
|
|
174
|
-
Make changes to your profile here. Click save when you're done.
|
|
175
|
-
</DialogDescription>
|
|
176
|
-
</DialogHeader>
|
|
177
|
-
<DialogBody className="grid gap-4">
|
|
178
|
-
<div className="grid grid-cols-4 items-center gap-4">
|
|
179
|
-
<Label htmlFor="name" className="text-right">
|
|
180
|
-
Name
|
|
181
|
-
</Label>
|
|
182
|
-
<Input id="name" defaultValue="Pedro Duarte" className="col-span-3" />
|
|
183
|
-
</div>
|
|
184
|
-
<div className="grid grid-cols-4 items-center gap-4">
|
|
185
|
-
<Label htmlFor="username" className="text-right">
|
|
186
|
-
Username
|
|
187
|
-
</Label>
|
|
188
|
-
<Input id="username" defaultValue="@peduarte" className="col-span-3" />
|
|
189
|
-
</div>
|
|
190
|
-
</DialogBody>
|
|
191
|
-
<DialogFooter>
|
|
192
|
-
<Button type="submit">
|
|
193
|
-
<Icon symbol="save" />
|
|
194
|
-
Save changes
|
|
195
|
-
</Button>
|
|
196
|
-
</DialogFooter>
|
|
197
|
-
</DialogContent>
|
|
198
|
-
</Dialog>;
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
### Compartir Link
|
|
202
|
-
|
|
203
|
-
```tsx
|
|
204
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
205
|
-
|
|
206
|
-
<Dialog>
|
|
207
|
-
<DialogTrigger asChild>
|
|
208
|
-
<Button variant="outline">
|
|
209
|
-
<Icon symbol="share" />
|
|
210
|
-
Share
|
|
211
|
-
</Button>
|
|
212
|
-
</DialogTrigger>
|
|
213
|
-
<DialogContent className="sm:max-w-md">
|
|
214
|
-
<DialogHeader>
|
|
215
|
-
<DialogTitle>Share link</DialogTitle>
|
|
216
|
-
<DialogDescription>
|
|
217
|
-
Anyone who has this link will be able to view this.
|
|
218
|
-
</DialogDescription>
|
|
219
|
-
</DialogHeader>
|
|
220
|
-
<DialogBody className="flex items-center space-x-2">
|
|
221
|
-
<div className="grid flex-1 gap-2">
|
|
222
|
-
<Label htmlFor="link" className="sr-only">
|
|
223
|
-
Link
|
|
224
|
-
</Label>
|
|
225
|
-
<Input
|
|
226
|
-
id="link"
|
|
227
|
-
defaultValue="https://ui.shadcn.com/docs/installation"
|
|
228
|
-
readOnly
|
|
229
|
-
/>
|
|
230
|
-
</div>
|
|
231
|
-
<Button type="submit" size="sm" className="px-3">
|
|
232
|
-
<Icon symbol="content_copy" />
|
|
233
|
-
</Button>
|
|
234
|
-
</DialogBody>
|
|
235
|
-
<DialogFooter className="sm:justify-start">
|
|
236
|
-
<DialogClose asChild>
|
|
237
|
-
<Button type="button" variant="secondary">
|
|
238
|
-
Close
|
|
239
|
-
</Button>
|
|
240
|
-
</DialogClose>
|
|
241
|
-
</DialogFooter>
|
|
242
|
-
</DialogContent>
|
|
243
|
-
</Dialog>;
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Confirmación de Eliminación
|
|
247
|
-
|
|
248
|
-
```tsx
|
|
249
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
250
|
-
import { Checkbox } from "@adamosuiteservices/ui/checkbox";
|
|
251
|
-
|
|
252
|
-
<Dialog>
|
|
253
|
-
<DialogTrigger asChild>
|
|
254
|
-
<Button variant="destructive">
|
|
255
|
-
<Icon symbol="delete" />
|
|
256
|
-
Delete Account
|
|
257
|
-
</Button>
|
|
258
|
-
</DialogTrigger>
|
|
259
|
-
<DialogContent>
|
|
260
|
-
<DialogHeader>
|
|
261
|
-
<DialogTitle>Delete Account</DialogTitle>
|
|
262
|
-
<DialogDescription>
|
|
263
|
-
This action cannot be undone. This will permanently delete your account
|
|
264
|
-
and remove all of your data from our servers.
|
|
265
|
-
</DialogDescription>
|
|
266
|
-
</DialogHeader>
|
|
267
|
-
<DialogBody>
|
|
268
|
-
<Label className="flex items-center gap-2 text-sm">
|
|
269
|
-
<Checkbox />I understand that this action is irreversible
|
|
270
|
-
</Label>
|
|
271
|
-
</DialogBody>
|
|
272
|
-
<DialogFooter>
|
|
273
|
-
<DialogClose asChild>
|
|
274
|
-
<Button variant="outline">Cancel</Button>
|
|
275
|
-
</DialogClose>
|
|
276
|
-
<Button variant="destructive">
|
|
277
|
-
<Icon symbol="delete" />
|
|
278
|
-
Delete Account
|
|
279
|
-
</Button>
|
|
280
|
-
</DialogFooter>
|
|
281
|
-
</DialogContent>
|
|
282
|
-
</Dialog>;
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### Crear Proyecto
|
|
286
|
-
|
|
287
|
-
```tsx
|
|
288
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
289
|
-
|
|
290
|
-
<Dialog>
|
|
291
|
-
<DialogTrigger asChild>
|
|
292
|
-
<Button>
|
|
293
|
-
<Icon symbol="add" />
|
|
294
|
-
New Project
|
|
295
|
-
</Button>
|
|
296
|
-
</DialogTrigger>
|
|
297
|
-
<DialogContent className="sm:max-w-[425px]">
|
|
298
|
-
<DialogHeader>
|
|
299
|
-
<DialogTitle>Create Project</DialogTitle>
|
|
300
|
-
<DialogDescription>
|
|
301
|
-
Create a new project to get started. You can always change these
|
|
302
|
-
settings later.
|
|
303
|
-
</DialogDescription>
|
|
304
|
-
</DialogHeader>
|
|
305
|
-
<DialogBody className="grid gap-4">
|
|
306
|
-
<div className="grid gap-2">
|
|
307
|
-
<Label htmlFor="project-name">Project Name</Label>
|
|
308
|
-
<Input id="project-name" placeholder="My Awesome Project" />
|
|
309
|
-
</div>
|
|
310
|
-
<div className="grid gap-2">
|
|
311
|
-
<Label htmlFor="description">Description</Label>
|
|
312
|
-
<Input id="description" placeholder="Brief description" />
|
|
313
|
-
</div>
|
|
314
|
-
<div className="grid gap-2">
|
|
315
|
-
<Label htmlFor="repository">Repository URL (optional)</Label>
|
|
316
|
-
<Input id="repository" placeholder="https://github.com/username/repo" />
|
|
317
|
-
</div>
|
|
318
|
-
<div className="flex items-center space-x-2">
|
|
319
|
-
<Checkbox id="public" />
|
|
320
|
-
<Label htmlFor="public" className="text-sm">
|
|
321
|
-
Make this project public
|
|
322
|
-
</Label>
|
|
323
|
-
</div>
|
|
324
|
-
</DialogBody>
|
|
325
|
-
<DialogFooter>
|
|
326
|
-
<DialogClose asChild>
|
|
327
|
-
<Button variant="outline">Cancel</Button>
|
|
328
|
-
</DialogClose>
|
|
329
|
-
<Button type="submit">
|
|
330
|
-
<Icon symbol="add" />
|
|
331
|
-
Create Project
|
|
332
|
-
</Button>
|
|
333
|
-
</DialogFooter>
|
|
334
|
-
</DialogContent>
|
|
335
|
-
</Dialog>;
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### Ver Detalles (Read-only)
|
|
339
|
-
|
|
340
|
-
```tsx
|
|
341
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
342
|
-
|
|
343
|
-
<Dialog>
|
|
344
|
-
<DialogTrigger asChild>
|
|
345
|
-
<Button variant="outline">
|
|
346
|
-
<Icon symbol="person" />
|
|
347
|
-
View Details
|
|
348
|
-
</Button>
|
|
349
|
-
</DialogTrigger>
|
|
350
|
-
<DialogContent>
|
|
351
|
-
<DialogHeader>
|
|
352
|
-
<DialogTitle>User Details</DialogTitle>
|
|
353
|
-
<DialogDescription>
|
|
354
|
-
View detailed information about this user account.
|
|
355
|
-
</DialogDescription>
|
|
356
|
-
</DialogHeader>
|
|
357
|
-
<DialogBody className="space-y-4">
|
|
358
|
-
<div className="grid grid-cols-3 gap-4">
|
|
359
|
-
<div className="font-medium">Name:</div>
|
|
360
|
-
<div className="col-span-2">John Doe</div>
|
|
361
|
-
</div>
|
|
362
|
-
<div className="grid grid-cols-3 gap-4">
|
|
363
|
-
<div className="font-medium">Email:</div>
|
|
364
|
-
<div className="col-span-2">john.doe@example.com</div>
|
|
365
|
-
</div>
|
|
366
|
-
<div className="grid grid-cols-3 gap-4">
|
|
367
|
-
<div className="font-medium">Role:</div>
|
|
368
|
-
<div className="col-span-2">Administrator</div>
|
|
369
|
-
</div>
|
|
370
|
-
<div className="grid grid-cols-3 gap-4">
|
|
371
|
-
<div className="font-medium">Joined:</div>
|
|
372
|
-
<div className="col-span-2">January 15, 2024</div>
|
|
373
|
-
</div>
|
|
374
|
-
<div className="grid grid-cols-3 gap-4">
|
|
375
|
-
<div className="font-medium">Last Active:</div>
|
|
376
|
-
<div className="col-span-2">2 hours ago</div>
|
|
377
|
-
</div>
|
|
378
|
-
</DialogBody>
|
|
379
|
-
<DialogFooter>
|
|
380
|
-
<DialogClose asChild>
|
|
381
|
-
<Button variant="outline">Close</Button>
|
|
382
|
-
</DialogClose>
|
|
383
|
-
<Button>
|
|
384
|
-
<Icon symbol="person" />
|
|
385
|
-
Edit User
|
|
386
|
-
</Button>
|
|
387
|
-
</DialogFooter>
|
|
388
|
-
</DialogContent>
|
|
389
|
-
</Dialog>;
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
### Información Estructurada
|
|
393
|
-
|
|
394
|
-
```tsx
|
|
395
|
-
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
396
|
-
|
|
397
|
-
<Dialog>
|
|
398
|
-
<DialogTrigger asChild>
|
|
399
|
-
<Button variant="outline">
|
|
400
|
-
<Icon symbol="info" />
|
|
401
|
-
More Info
|
|
402
|
-
</Button>
|
|
403
|
-
</DialogTrigger>
|
|
404
|
-
<DialogContent>
|
|
405
|
-
<DialogHeader>
|
|
406
|
-
<DialogTitle>Important Information</DialogTitle>
|
|
407
|
-
<DialogDescription>
|
|
408
|
-
Please read the following information carefully before proceeding.
|
|
409
|
-
</DialogDescription>
|
|
410
|
-
</DialogHeader>
|
|
411
|
-
<DialogBody className="space-y-4 text-sm">
|
|
412
|
-
<div>
|
|
413
|
-
<h4 className="font-medium mb-2">Data Processing</h4>
|
|
414
|
-
<p className="text-muted-foreground">
|
|
415
|
-
Your data will be processed according to our privacy policy. We ensure
|
|
416
|
-
full compliance with GDPR and other data protection regulations.
|
|
417
|
-
</p>
|
|
418
|
-
</div>
|
|
419
|
-
<div>
|
|
420
|
-
<h4 className="font-medium mb-2">Security</h4>
|
|
421
|
-
<p className="text-muted-foreground">
|
|
422
|
-
All data is encrypted both in transit and at rest using
|
|
423
|
-
industry-standard encryption protocols.
|
|
424
|
-
</p>
|
|
425
|
-
</div>
|
|
426
|
-
<div>
|
|
427
|
-
<h4 className="font-medium mb-2">Support</h4>
|
|
428
|
-
<p className="text-muted-foreground">
|
|
429
|
-
If you have any questions or concerns, please contact our support team
|
|
430
|
-
at support@example.com.
|
|
431
|
-
</p>
|
|
432
|
-
</div>
|
|
433
|
-
</DialogBody>
|
|
434
|
-
<DialogFooter>
|
|
435
|
-
<DialogClose asChild>
|
|
436
|
-
<Button>Got it</Button>
|
|
437
|
-
</DialogClose>
|
|
438
|
-
</DialogFooter>
|
|
439
|
-
</DialogContent>
|
|
440
|
-
</Dialog>;
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
### Sin Botón de Cerrar
|
|
444
|
-
|
|
445
|
-
```tsx
|
|
446
|
-
<Dialog>
|
|
447
|
-
<DialogTrigger asChild>
|
|
448
|
-
<Button variant="outline">Open (No X)</Button>
|
|
449
|
-
</DialogTrigger>
|
|
450
|
-
<DialogContent showCloseButton={false}>
|
|
451
|
-
<DialogHeader>
|
|
452
|
-
<DialogTitle>Custom Close Behavior</DialogTitle>
|
|
453
|
-
<DialogDescription>
|
|
454
|
-
This dialog doesn't have the X button. You must use the action buttons.
|
|
455
|
-
</DialogDescription>
|
|
456
|
-
</DialogHeader>
|
|
457
|
-
<DialogBody>
|
|
458
|
-
<p className="text-sm text-muted-foreground">
|
|
459
|
-
This pattern is useful when you want to force users to make a deliberate
|
|
460
|
-
choice rather than accidentally closing the dialog.
|
|
461
|
-
</p>
|
|
462
|
-
</DialogBody>
|
|
463
|
-
<DialogFooter>
|
|
464
|
-
<DialogClose asChild>
|
|
465
|
-
<Button variant="outline">Cancel</Button>
|
|
466
|
-
</DialogClose>
|
|
467
|
-
<DialogClose asChild>
|
|
468
|
-
<Button>Confirm</Button>
|
|
469
|
-
</DialogClose>
|
|
470
|
-
</DialogFooter>
|
|
471
|
-
</DialogContent>
|
|
472
|
-
</Dialog>
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
**Uso**: Forzar decisión deliberada, prevenir cierre accidental
|
|
476
|
-
|
|
477
|
-
### Controlado
|
|
478
|
-
|
|
479
|
-
```tsx
|
|
480
|
-
import { useState } from "react";
|
|
481
|
-
|
|
482
|
-
function App() {
|
|
483
|
-
const [open, setOpen] = useState(false);
|
|
484
|
-
|
|
485
|
-
return (
|
|
486
|
-
<Dialog open={open} onOpenChange={setOpen}>
|
|
487
|
-
<DialogTrigger>Open Dialog</DialogTrigger>
|
|
488
|
-
<DialogContent>
|
|
489
|
-
<DialogHeader>
|
|
490
|
-
<DialogTitle>Controlled Dialog</DialogTitle>
|
|
491
|
-
</DialogHeader>
|
|
492
|
-
<Button onClick={() => setOpen(false)}>Close Programmatically</Button>
|
|
493
|
-
</DialogContent>
|
|
494
|
-
</Dialog>
|
|
495
|
-
);
|
|
496
|
-
}
|
|
497
|
-
```
|
|
498
|
-
|
|
499
|
-
### Con Tema Custom
|
|
500
|
-
|
|
501
|
-
```tsx
|
|
502
|
-
<DialogContent theme="dark">
|
|
503
|
-
<DialogHeader>
|
|
504
|
-
<DialogTitle>Dark Theme Dialog</DialogTitle>
|
|
505
|
-
<DialogDescription>This dialog uses a custom theme.</DialogDescription>
|
|
506
|
-
</DialogHeader>
|
|
507
|
-
</DialogContent>
|
|
508
|
-
```
|
|
509
|
-
|
|
510
|
-
**Temas disponibles**: `default`, `dark`, `pay`, `sign`, `risk`, `id`
|
|
511
|
-
|
|
512
|
-
## Casos de Uso Comunes
|
|
513
|
-
|
|
514
|
-
**Formularios de edición**: Edit profile, settings, preferences
|
|
515
|
-
**Confirmaciones destructivas**: Delete account, remove items, clear data
|
|
516
|
-
**Crear nuevos items**: New project, add user, create record
|
|
517
|
-
**Compartir contenido**: Share links, export data, send invitations
|
|
518
|
-
**Ver detalles**: User info, product details, transaction summary
|
|
519
|
-
**Información**: Disclaimers, terms, help content
|
|
520
|
-
|
|
521
|
-
## Estados y Data Attributes
|
|
522
|
-
|
|
523
|
-
### Dialog States
|
|
524
|
-
|
|
525
|
-
- **Open**: `data-[state=open]` → animaciones de entrada
|
|
526
|
-
- **Closed**: `data-[state=closed]` → animaciones de salida
|
|
527
|
-
|
|
528
|
-
### Overlay Animations
|
|
529
|
-
|
|
530
|
-
- **Opening**: `fade-in-0`
|
|
531
|
-
- **Closing**: `fade-out-0`
|
|
532
|
-
|
|
533
|
-
### Content Animations
|
|
534
|
-
|
|
535
|
-
- **Opening**: `fade-in-0`, `zoom-in-95`
|
|
536
|
-
- **Closing**: `fade-out-0`, `zoom-out-95`
|
|
537
|
-
- **Duration**: `200ms`
|
|
538
|
-
|
|
539
|
-
## Navegación por Teclado
|
|
540
|
-
|
|
541
|
-
- ✅ **Escape**: Cierra el dialog (previene con `onEscapeKeyDown`)
|
|
542
|
-
- ✅ **Tab**: Navega entre elementos focusables dentro del dialog
|
|
543
|
-
- ✅ **Shift+Tab**: Navegación inversa
|
|
544
|
-
- ✅ **Enter**: Activa botón/elemento enfocado
|
|
545
|
-
|
|
546
|
-
## Accesibilidad
|
|
547
|
-
|
|
548
|
-
- ✅ **ARIA**: `role="dialog"`, `aria-labelledby` (title), `aria-describedby` (description)
|
|
549
|
-
- ✅ **Focus trap**: Focus queda dentro del dialog mientras está abierto
|
|
550
|
-
- ✅ **Focus restoration**: Focus vuelve al trigger al cerrar
|
|
551
|
-
- ✅ **Screen readers**: Anuncia título, descripción, y contenido
|
|
552
|
-
- ✅ **Keyboard navigation**: Completamente navegable por teclado
|
|
553
|
-
- ✅ **Close button**: `aria-label="Close"` en botón X
|
|
554
|
-
- ✅ **Modal behavior**: Bloquea interacción con contenido externo
|
|
555
|
-
|
|
556
|
-
## Notas de Implementación
|
|
557
|
-
|
|
558
|
-
- **Basado en Radix UI**: `@radix-ui/react-dialog`
|
|
559
|
-
- **Portal rendering**: Content se renderiza en `document.body`
|
|
560
|
-
- **Overlay**: `bg-black/50`, `fixed inset-0`, `z-50`
|
|
561
|
-
- **Centrado**: `top-[50%] left-[50%]`, `translate-x-[-50%] translate-y-[-50%]`
|
|
562
|
-
- **Responsive**: `max-w-[calc(100%-2rem)]` en mobile, `sm:max-w-lg` en desktop
|
|
563
|
-
- **Close button**: XIcon automático en esquina superior derecha si `showCloseButton={true}`
|
|
564
|
-
- **Auto-close**: Cierra con Escape, clic fuera, o DialogClose
|
|
565
|
-
- **Focus management**: Primer elemento focusable recibe focus al abrir
|
|
566
|
-
- **Theme support**: Prop `theme` aplica `data-theme` al content
|
|
567
|
-
- **Z-index**: 50 para overlay y content
|
|
568
|
-
|
|
569
|
-
## Responsive Behavior
|
|
570
|
-
|
|
571
|
-
### Mobile
|
|
572
|
-
|
|
573
|
-
- `max-w-[calc(100%-2rem)]`: Margen de 1rem a cada lado
|
|
574
|
-
- `text-center`: Header centrado
|
|
575
|
-
- `flex-col-reverse`: Footer con botones apilados (Confirm arriba, Cancel abajo)
|
|
576
|
-
|
|
577
|
-
### Desktop (sm+)
|
|
578
|
-
|
|
579
|
-
- `sm:max-w-lg`: Ancho máximo 32rem
|
|
580
|
-
- `sm:text-left`: Header alineado a izquierda
|
|
581
|
-
- `sm:flex-row sm:justify-end`: Footer horizontal con botones a la derecha
|
|
582
|
-
|
|
583
|
-
## Customización de Ancho
|
|
584
|
-
|
|
585
|
-
```tsx
|
|
586
|
-
{
|
|
587
|
-
/* Small dialog */
|
|
588
|
-
}
|
|
589
|
-
<DialogContent className="sm:max-w-md">...</DialogContent>;
|
|
590
|
-
|
|
591
|
-
{
|
|
592
|
-
/* Medium (default) */
|
|
593
|
-
}
|
|
594
|
-
<DialogContent className="sm:max-w-lg">...</DialogContent>;
|
|
595
|
-
|
|
596
|
-
{
|
|
597
|
-
/* Large */
|
|
598
|
-
}
|
|
599
|
-
<DialogContent className="sm:max-w-2xl">...</DialogContent>;
|
|
600
|
-
|
|
601
|
-
{
|
|
602
|
-
/* Extra large */
|
|
603
|
-
}
|
|
604
|
-
<DialogContent className="sm:max-w-4xl">...</DialogContent>;
|
|
605
|
-
|
|
606
|
-
{
|
|
607
|
-
/* Full width with margin */
|
|
608
|
-
}
|
|
609
|
-
<DialogContent className="sm:max-w-[90vw]">...</DialogContent>;
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
## Troubleshooting
|
|
613
|
-
|
|
614
|
-
**Dialog no cierra con Escape**: Verifica que no estés previniendo evento con `onEscapeKeyDown`
|
|
615
|
-
**Dialog no cierra al hacer clic fuera**: Verifica `onPointerDownOutside` o `modal={false}`
|
|
616
|
-
**Focus no vuelve al trigger**: Asegúrate de que el trigger sigue en el DOM
|
|
617
|
-
**Scroll bloqueado después de cerrar**: Radix maneja esto automáticamente, verifica conflictos con CSS
|
|
618
|
-
**Content no centrado**: Evita `transform` CSS en elementos padre que afecten positioning
|
|
619
|
-
**Animaciones no funcionan**: Verifica que `@tailwindcss/animate` esté instalado
|
|
620
|
-
**Botón X no aparece**: Verifica `showCloseButton={true}` (default)
|
|
621
|
-
**Overlay no oscurece**: Z-index conflict, aumenta z-index del overlay
|
|
622
|
-
**Title/Description no anunciados**: Asegúrate de usar componentes DialogTitle y DialogDescription (no divs)
|
|
623
|
-
|
|
624
|
-
## Referencias
|
|
625
|
-
|
|
626
|
-
- **Radix UI Dialog**: https://www.radix-ui.com/primitives/docs/components/dialog
|
|
627
|
-
- **shadcn/ui Dialog**: https://ui.shadcn.com/docs/components/dialog
|
|
628
|
-
- **ARIA Dialog Pattern**: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
|
|
1
|
+
# Dialog
|
|
2
|
+
|
|
3
|
+
Ventana modal centrada sobre overlay semi-transparente, basada en Radix UI. Soporta formularios, confirmaciones, información, y acciones. Útil para capturar atención del usuario en tareas críticas.
|
|
4
|
+
|
|
5
|
+
## Importación
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import {
|
|
9
|
+
Dialog,
|
|
10
|
+
DialogTrigger,
|
|
11
|
+
DialogContent,
|
|
12
|
+
DialogHeader,
|
|
13
|
+
DialogTitle,
|
|
14
|
+
DialogDescription,
|
|
15
|
+
DialogBody,
|
|
16
|
+
DialogFooter,
|
|
17
|
+
DialogClose,
|
|
18
|
+
DialogOverlay,
|
|
19
|
+
DialogPortal,
|
|
20
|
+
} from "@adamosuiteservices/ui/dialog";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Anatomía
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
<Dialog>
|
|
27
|
+
<DialogTrigger>Open Dialog</DialogTrigger>
|
|
28
|
+
<DialogContent>
|
|
29
|
+
<DialogHeader>
|
|
30
|
+
<DialogTitle>Title</DialogTitle>
|
|
31
|
+
<DialogDescription>Description text</DialogDescription>
|
|
32
|
+
</DialogHeader>
|
|
33
|
+
<DialogBody>{/* Main content */}</DialogBody>
|
|
34
|
+
<DialogFooter>
|
|
35
|
+
<DialogClose asChild>
|
|
36
|
+
<Button variant="outline">Cancel</Button>
|
|
37
|
+
</DialogClose>
|
|
38
|
+
<Button>Confirm</Button>
|
|
39
|
+
</DialogFooter>
|
|
40
|
+
</DialogContent>
|
|
41
|
+
</Dialog>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Componentes**: 10 (Dialog, Trigger, Content, Header, Title, Description, Body, Footer, Close, Overlay, Portal)
|
|
45
|
+
|
|
46
|
+
## Props Principales
|
|
47
|
+
|
|
48
|
+
### Dialog (Root)
|
|
49
|
+
|
|
50
|
+
| Prop | Tipo | Default | Descripción |
|
|
51
|
+
| -------------- | ------------------------- | ------- | ----------------------------------------- |
|
|
52
|
+
| `open` | `boolean` | - | Estado controlado del dialog |
|
|
53
|
+
| `onOpenChange` | `(open: boolean) => void` | - | Callback cuando cambia estado |
|
|
54
|
+
| `defaultOpen` | `boolean` | `false` | Estado inicial no controlado |
|
|
55
|
+
| `modal` | `boolean` | `true` | Bloquea interacción con contenido externo |
|
|
56
|
+
|
|
57
|
+
### DialogTrigger
|
|
58
|
+
|
|
59
|
+
| Prop | Tipo | Descripción |
|
|
60
|
+
| ----------- | --------- | -------------------------------------------------- |
|
|
61
|
+
| `asChild` | `boolean` | Pasa props al child en lugar de renderizar wrapper |
|
|
62
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
63
|
+
|
|
64
|
+
### DialogContent
|
|
65
|
+
|
|
66
|
+
| Prop | Tipo | Default | Descripción |
|
|
67
|
+
| ---------------------- | ----------------- | ------- | ------------------------------------------------------- |
|
|
68
|
+
| `showCloseButton` | `boolean` | `true` | Muestra botón X en esquina superior derecha |
|
|
69
|
+
| `theme` | `Theme` | - | Tema personalizado (default, dark, pay, sign, risk, id) |
|
|
70
|
+
| `className` | `string` | - | Clases CSS adicionales |
|
|
71
|
+
| `onEscapeKeyDown` | `(event) => void` | - | Callback al presionar Escape |
|
|
72
|
+
| `onPointerDownOutside` | `(event) => void` | - | Callback al hacer clic fuera |
|
|
73
|
+
| `onInteractOutside` | `(event) => void` | - | Callback al interactuar fuera |
|
|
74
|
+
|
|
75
|
+
**Estilos default**: `max-w-lg`, `max-w-[calc(100%-2rem)]` en mobile, centrado, `rounded-lg`, `p-6`, `shadow-lg`
|
|
76
|
+
|
|
77
|
+
### DialogTitle
|
|
78
|
+
|
|
79
|
+
| Prop | Tipo | Descripción |
|
|
80
|
+
| ----------- | -------- | ---------------------- |
|
|
81
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
82
|
+
|
|
83
|
+
**Estilos**: `text-lg`, `font-semibold`, `leading-none`
|
|
84
|
+
|
|
85
|
+
### DialogDescription
|
|
86
|
+
|
|
87
|
+
| Prop | Tipo | Descripción |
|
|
88
|
+
| ----------- | -------- | ---------------------- |
|
|
89
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
90
|
+
|
|
91
|
+
**Estilos**: `text-sm`, `text-muted-foreground`
|
|
92
|
+
|
|
93
|
+
### DialogBody
|
|
94
|
+
|
|
95
|
+
| Prop | Tipo | Descripción |
|
|
96
|
+
| ----------- | -------- | ---------------------- |
|
|
97
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
98
|
+
|
|
99
|
+
**Estilos**: `mt-2 mb-6`
|
|
100
|
+
**Propósito**: Contenedor para el contenido principal del dialog entre el header y footer. Proporciona espaciado vertical consistente.
|
|
101
|
+
|
|
102
|
+
### DialogHeader
|
|
103
|
+
|
|
104
|
+
| Prop | Tipo | Descripción |
|
|
105
|
+
| ----------- | -------- | ---------------------- |
|
|
106
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
107
|
+
|
|
108
|
+
**Estilos**: `flex flex-col gap-2`, `text-center` en mobile, `sm:text-left`
|
|
109
|
+
|
|
110
|
+
### DialogFooter
|
|
111
|
+
|
|
112
|
+
| Prop | Tipo | Descripción |
|
|
113
|
+
| ----------- | -------- | ---------------------- |
|
|
114
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
115
|
+
|
|
116
|
+
**Estilos**: `flex-col-reverse` en mobile, `sm:flex-row sm:justify-end`, `gap-2`
|
|
117
|
+
|
|
118
|
+
### DialogClose
|
|
119
|
+
|
|
120
|
+
| Prop | Tipo | Descripción |
|
|
121
|
+
| ----------- | --------- | ------------------------------------------------- |
|
|
122
|
+
| `asChild` | `boolean` | Pasa props al child en lugar de renderizar button |
|
|
123
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
124
|
+
|
|
125
|
+
## Patrones de Uso
|
|
126
|
+
|
|
127
|
+
### Básico
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<Dialog>
|
|
131
|
+
<DialogTrigger>Open</DialogTrigger>
|
|
132
|
+
<DialogContent>
|
|
133
|
+
<DialogHeader>
|
|
134
|
+
<DialogTitle>Are you absolutely sure?</DialogTitle>
|
|
135
|
+
<DialogDescription>
|
|
136
|
+
This action cannot be undone. This will permanently delete your account.
|
|
137
|
+
</DialogDescription>
|
|
138
|
+
</DialogHeader>
|
|
139
|
+
</DialogContent>
|
|
140
|
+
</Dialog>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Con Trigger Custom (asChild)
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
<Dialog>
|
|
147
|
+
<DialogTrigger asChild>
|
|
148
|
+
<Button variant="outline">Edit Profile</Button>
|
|
149
|
+
</DialogTrigger>
|
|
150
|
+
<DialogContent>
|
|
151
|
+
<DialogHeader>
|
|
152
|
+
<DialogTitle>Edit Profile</DialogTitle>
|
|
153
|
+
<DialogDescription>Make changes to your profile here.</DialogDescription>
|
|
154
|
+
</DialogHeader>
|
|
155
|
+
</DialogContent>
|
|
156
|
+
</Dialog>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Formulario de Edición
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
163
|
+
import { Input } from "@adamosuiteservices/ui/input";
|
|
164
|
+
import { Label } from "@adamosuiteservices/ui/label";
|
|
165
|
+
|
|
166
|
+
<Dialog>
|
|
167
|
+
<DialogTrigger asChild>
|
|
168
|
+
<Button variant="outline">Edit Profile</Button>
|
|
169
|
+
</DialogTrigger>
|
|
170
|
+
<DialogContent className="sm:max-w-[425px]">
|
|
171
|
+
<DialogHeader>
|
|
172
|
+
<DialogTitle>Edit profile</DialogTitle>
|
|
173
|
+
<DialogDescription>
|
|
174
|
+
Make changes to your profile here. Click save when you're done.
|
|
175
|
+
</DialogDescription>
|
|
176
|
+
</DialogHeader>
|
|
177
|
+
<DialogBody className="grid gap-4">
|
|
178
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
179
|
+
<Label htmlFor="name" className="text-right">
|
|
180
|
+
Name
|
|
181
|
+
</Label>
|
|
182
|
+
<Input id="name" defaultValue="Pedro Duarte" className="col-span-3" />
|
|
183
|
+
</div>
|
|
184
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
185
|
+
<Label htmlFor="username" className="text-right">
|
|
186
|
+
Username
|
|
187
|
+
</Label>
|
|
188
|
+
<Input id="username" defaultValue="@peduarte" className="col-span-3" />
|
|
189
|
+
</div>
|
|
190
|
+
</DialogBody>
|
|
191
|
+
<DialogFooter>
|
|
192
|
+
<Button type="submit">
|
|
193
|
+
<Icon symbol="save" />
|
|
194
|
+
Save changes
|
|
195
|
+
</Button>
|
|
196
|
+
</DialogFooter>
|
|
197
|
+
</DialogContent>
|
|
198
|
+
</Dialog>;
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Compartir Link
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
205
|
+
|
|
206
|
+
<Dialog>
|
|
207
|
+
<DialogTrigger asChild>
|
|
208
|
+
<Button variant="outline">
|
|
209
|
+
<Icon symbol="share" />
|
|
210
|
+
Share
|
|
211
|
+
</Button>
|
|
212
|
+
</DialogTrigger>
|
|
213
|
+
<DialogContent className="sm:max-w-md">
|
|
214
|
+
<DialogHeader>
|
|
215
|
+
<DialogTitle>Share link</DialogTitle>
|
|
216
|
+
<DialogDescription>
|
|
217
|
+
Anyone who has this link will be able to view this.
|
|
218
|
+
</DialogDescription>
|
|
219
|
+
</DialogHeader>
|
|
220
|
+
<DialogBody className="flex items-center space-x-2">
|
|
221
|
+
<div className="grid flex-1 gap-2">
|
|
222
|
+
<Label htmlFor="link" className="sr-only">
|
|
223
|
+
Link
|
|
224
|
+
</Label>
|
|
225
|
+
<Input
|
|
226
|
+
id="link"
|
|
227
|
+
defaultValue="https://ui.shadcn.com/docs/installation"
|
|
228
|
+
readOnly
|
|
229
|
+
/>
|
|
230
|
+
</div>
|
|
231
|
+
<Button type="submit" size="sm" className="px-3">
|
|
232
|
+
<Icon symbol="content_copy" />
|
|
233
|
+
</Button>
|
|
234
|
+
</DialogBody>
|
|
235
|
+
<DialogFooter className="sm:justify-start">
|
|
236
|
+
<DialogClose asChild>
|
|
237
|
+
<Button type="button" variant="secondary">
|
|
238
|
+
Close
|
|
239
|
+
</Button>
|
|
240
|
+
</DialogClose>
|
|
241
|
+
</DialogFooter>
|
|
242
|
+
</DialogContent>
|
|
243
|
+
</Dialog>;
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Confirmación de Eliminación
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
250
|
+
import { Checkbox } from "@adamosuiteservices/ui/checkbox";
|
|
251
|
+
|
|
252
|
+
<Dialog>
|
|
253
|
+
<DialogTrigger asChild>
|
|
254
|
+
<Button variant="destructive">
|
|
255
|
+
<Icon symbol="delete" />
|
|
256
|
+
Delete Account
|
|
257
|
+
</Button>
|
|
258
|
+
</DialogTrigger>
|
|
259
|
+
<DialogContent>
|
|
260
|
+
<DialogHeader>
|
|
261
|
+
<DialogTitle>Delete Account</DialogTitle>
|
|
262
|
+
<DialogDescription>
|
|
263
|
+
This action cannot be undone. This will permanently delete your account
|
|
264
|
+
and remove all of your data from our servers.
|
|
265
|
+
</DialogDescription>
|
|
266
|
+
</DialogHeader>
|
|
267
|
+
<DialogBody>
|
|
268
|
+
<Label className="flex items-center gap-2 text-sm">
|
|
269
|
+
<Checkbox />I understand that this action is irreversible
|
|
270
|
+
</Label>
|
|
271
|
+
</DialogBody>
|
|
272
|
+
<DialogFooter>
|
|
273
|
+
<DialogClose asChild>
|
|
274
|
+
<Button variant="outline">Cancel</Button>
|
|
275
|
+
</DialogClose>
|
|
276
|
+
<Button variant="destructive">
|
|
277
|
+
<Icon symbol="delete" />
|
|
278
|
+
Delete Account
|
|
279
|
+
</Button>
|
|
280
|
+
</DialogFooter>
|
|
281
|
+
</DialogContent>
|
|
282
|
+
</Dialog>;
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Crear Proyecto
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
289
|
+
|
|
290
|
+
<Dialog>
|
|
291
|
+
<DialogTrigger asChild>
|
|
292
|
+
<Button>
|
|
293
|
+
<Icon symbol="add" />
|
|
294
|
+
New Project
|
|
295
|
+
</Button>
|
|
296
|
+
</DialogTrigger>
|
|
297
|
+
<DialogContent className="sm:max-w-[425px]">
|
|
298
|
+
<DialogHeader>
|
|
299
|
+
<DialogTitle>Create Project</DialogTitle>
|
|
300
|
+
<DialogDescription>
|
|
301
|
+
Create a new project to get started. You can always change these
|
|
302
|
+
settings later.
|
|
303
|
+
</DialogDescription>
|
|
304
|
+
</DialogHeader>
|
|
305
|
+
<DialogBody className="grid gap-4">
|
|
306
|
+
<div className="grid gap-2">
|
|
307
|
+
<Label htmlFor="project-name">Project Name</Label>
|
|
308
|
+
<Input id="project-name" placeholder="My Awesome Project" />
|
|
309
|
+
</div>
|
|
310
|
+
<div className="grid gap-2">
|
|
311
|
+
<Label htmlFor="description">Description</Label>
|
|
312
|
+
<Input id="description" placeholder="Brief description" />
|
|
313
|
+
</div>
|
|
314
|
+
<div className="grid gap-2">
|
|
315
|
+
<Label htmlFor="repository">Repository URL (optional)</Label>
|
|
316
|
+
<Input id="repository" placeholder="https://github.com/username/repo" />
|
|
317
|
+
</div>
|
|
318
|
+
<div className="flex items-center space-x-2">
|
|
319
|
+
<Checkbox id="public" />
|
|
320
|
+
<Label htmlFor="public" className="text-sm">
|
|
321
|
+
Make this project public
|
|
322
|
+
</Label>
|
|
323
|
+
</div>
|
|
324
|
+
</DialogBody>
|
|
325
|
+
<DialogFooter>
|
|
326
|
+
<DialogClose asChild>
|
|
327
|
+
<Button variant="outline">Cancel</Button>
|
|
328
|
+
</DialogClose>
|
|
329
|
+
<Button type="submit">
|
|
330
|
+
<Icon symbol="add" />
|
|
331
|
+
Create Project
|
|
332
|
+
</Button>
|
|
333
|
+
</DialogFooter>
|
|
334
|
+
</DialogContent>
|
|
335
|
+
</Dialog>;
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Ver Detalles (Read-only)
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
342
|
+
|
|
343
|
+
<Dialog>
|
|
344
|
+
<DialogTrigger asChild>
|
|
345
|
+
<Button variant="outline">
|
|
346
|
+
<Icon symbol="person" />
|
|
347
|
+
View Details
|
|
348
|
+
</Button>
|
|
349
|
+
</DialogTrigger>
|
|
350
|
+
<DialogContent>
|
|
351
|
+
<DialogHeader>
|
|
352
|
+
<DialogTitle>User Details</DialogTitle>
|
|
353
|
+
<DialogDescription>
|
|
354
|
+
View detailed information about this user account.
|
|
355
|
+
</DialogDescription>
|
|
356
|
+
</DialogHeader>
|
|
357
|
+
<DialogBody className="space-y-4">
|
|
358
|
+
<div className="grid grid-cols-3 gap-4">
|
|
359
|
+
<div className="font-medium">Name:</div>
|
|
360
|
+
<div className="col-span-2">John Doe</div>
|
|
361
|
+
</div>
|
|
362
|
+
<div className="grid grid-cols-3 gap-4">
|
|
363
|
+
<div className="font-medium">Email:</div>
|
|
364
|
+
<div className="col-span-2">john.doe@example.com</div>
|
|
365
|
+
</div>
|
|
366
|
+
<div className="grid grid-cols-3 gap-4">
|
|
367
|
+
<div className="font-medium">Role:</div>
|
|
368
|
+
<div className="col-span-2">Administrator</div>
|
|
369
|
+
</div>
|
|
370
|
+
<div className="grid grid-cols-3 gap-4">
|
|
371
|
+
<div className="font-medium">Joined:</div>
|
|
372
|
+
<div className="col-span-2">January 15, 2024</div>
|
|
373
|
+
</div>
|
|
374
|
+
<div className="grid grid-cols-3 gap-4">
|
|
375
|
+
<div className="font-medium">Last Active:</div>
|
|
376
|
+
<div className="col-span-2">2 hours ago</div>
|
|
377
|
+
</div>
|
|
378
|
+
</DialogBody>
|
|
379
|
+
<DialogFooter>
|
|
380
|
+
<DialogClose asChild>
|
|
381
|
+
<Button variant="outline">Close</Button>
|
|
382
|
+
</DialogClose>
|
|
383
|
+
<Button>
|
|
384
|
+
<Icon symbol="person" />
|
|
385
|
+
Edit User
|
|
386
|
+
</Button>
|
|
387
|
+
</DialogFooter>
|
|
388
|
+
</DialogContent>
|
|
389
|
+
</Dialog>;
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Información Estructurada
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
import { Icon } from "@adamosuiteservices/ui/icon";
|
|
396
|
+
|
|
397
|
+
<Dialog>
|
|
398
|
+
<DialogTrigger asChild>
|
|
399
|
+
<Button variant="outline">
|
|
400
|
+
<Icon symbol="info" />
|
|
401
|
+
More Info
|
|
402
|
+
</Button>
|
|
403
|
+
</DialogTrigger>
|
|
404
|
+
<DialogContent>
|
|
405
|
+
<DialogHeader>
|
|
406
|
+
<DialogTitle>Important Information</DialogTitle>
|
|
407
|
+
<DialogDescription>
|
|
408
|
+
Please read the following information carefully before proceeding.
|
|
409
|
+
</DialogDescription>
|
|
410
|
+
</DialogHeader>
|
|
411
|
+
<DialogBody className="space-y-4 text-sm">
|
|
412
|
+
<div>
|
|
413
|
+
<h4 className="font-medium mb-2">Data Processing</h4>
|
|
414
|
+
<p className="text-muted-foreground">
|
|
415
|
+
Your data will be processed according to our privacy policy. We ensure
|
|
416
|
+
full compliance with GDPR and other data protection regulations.
|
|
417
|
+
</p>
|
|
418
|
+
</div>
|
|
419
|
+
<div>
|
|
420
|
+
<h4 className="font-medium mb-2">Security</h4>
|
|
421
|
+
<p className="text-muted-foreground">
|
|
422
|
+
All data is encrypted both in transit and at rest using
|
|
423
|
+
industry-standard encryption protocols.
|
|
424
|
+
</p>
|
|
425
|
+
</div>
|
|
426
|
+
<div>
|
|
427
|
+
<h4 className="font-medium mb-2">Support</h4>
|
|
428
|
+
<p className="text-muted-foreground">
|
|
429
|
+
If you have any questions or concerns, please contact our support team
|
|
430
|
+
at support@example.com.
|
|
431
|
+
</p>
|
|
432
|
+
</div>
|
|
433
|
+
</DialogBody>
|
|
434
|
+
<DialogFooter>
|
|
435
|
+
<DialogClose asChild>
|
|
436
|
+
<Button>Got it</Button>
|
|
437
|
+
</DialogClose>
|
|
438
|
+
</DialogFooter>
|
|
439
|
+
</DialogContent>
|
|
440
|
+
</Dialog>;
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Sin Botón de Cerrar
|
|
444
|
+
|
|
445
|
+
```tsx
|
|
446
|
+
<Dialog>
|
|
447
|
+
<DialogTrigger asChild>
|
|
448
|
+
<Button variant="outline">Open (No X)</Button>
|
|
449
|
+
</DialogTrigger>
|
|
450
|
+
<DialogContent showCloseButton={false}>
|
|
451
|
+
<DialogHeader>
|
|
452
|
+
<DialogTitle>Custom Close Behavior</DialogTitle>
|
|
453
|
+
<DialogDescription>
|
|
454
|
+
This dialog doesn't have the X button. You must use the action buttons.
|
|
455
|
+
</DialogDescription>
|
|
456
|
+
</DialogHeader>
|
|
457
|
+
<DialogBody>
|
|
458
|
+
<p className="text-sm text-muted-foreground">
|
|
459
|
+
This pattern is useful when you want to force users to make a deliberate
|
|
460
|
+
choice rather than accidentally closing the dialog.
|
|
461
|
+
</p>
|
|
462
|
+
</DialogBody>
|
|
463
|
+
<DialogFooter>
|
|
464
|
+
<DialogClose asChild>
|
|
465
|
+
<Button variant="outline">Cancel</Button>
|
|
466
|
+
</DialogClose>
|
|
467
|
+
<DialogClose asChild>
|
|
468
|
+
<Button>Confirm</Button>
|
|
469
|
+
</DialogClose>
|
|
470
|
+
</DialogFooter>
|
|
471
|
+
</DialogContent>
|
|
472
|
+
</Dialog>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
**Uso**: Forzar decisión deliberada, prevenir cierre accidental
|
|
476
|
+
|
|
477
|
+
### Controlado
|
|
478
|
+
|
|
479
|
+
```tsx
|
|
480
|
+
import { useState } from "react";
|
|
481
|
+
|
|
482
|
+
function App() {
|
|
483
|
+
const [open, setOpen] = useState(false);
|
|
484
|
+
|
|
485
|
+
return (
|
|
486
|
+
<Dialog open={open} onOpenChange={setOpen}>
|
|
487
|
+
<DialogTrigger>Open Dialog</DialogTrigger>
|
|
488
|
+
<DialogContent>
|
|
489
|
+
<DialogHeader>
|
|
490
|
+
<DialogTitle>Controlled Dialog</DialogTitle>
|
|
491
|
+
</DialogHeader>
|
|
492
|
+
<Button onClick={() => setOpen(false)}>Close Programmatically</Button>
|
|
493
|
+
</DialogContent>
|
|
494
|
+
</Dialog>
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Con Tema Custom
|
|
500
|
+
|
|
501
|
+
```tsx
|
|
502
|
+
<DialogContent theme="dark">
|
|
503
|
+
<DialogHeader>
|
|
504
|
+
<DialogTitle>Dark Theme Dialog</DialogTitle>
|
|
505
|
+
<DialogDescription>This dialog uses a custom theme.</DialogDescription>
|
|
506
|
+
</DialogHeader>
|
|
507
|
+
</DialogContent>
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
**Temas disponibles**: `default`, `dark`, `pay`, `sign`, `risk`, `id`
|
|
511
|
+
|
|
512
|
+
## Casos de Uso Comunes
|
|
513
|
+
|
|
514
|
+
**Formularios de edición**: Edit profile, settings, preferences
|
|
515
|
+
**Confirmaciones destructivas**: Delete account, remove items, clear data
|
|
516
|
+
**Crear nuevos items**: New project, add user, create record
|
|
517
|
+
**Compartir contenido**: Share links, export data, send invitations
|
|
518
|
+
**Ver detalles**: User info, product details, transaction summary
|
|
519
|
+
**Información**: Disclaimers, terms, help content
|
|
520
|
+
|
|
521
|
+
## Estados y Data Attributes
|
|
522
|
+
|
|
523
|
+
### Dialog States
|
|
524
|
+
|
|
525
|
+
- **Open**: `data-[state=open]` → animaciones de entrada
|
|
526
|
+
- **Closed**: `data-[state=closed]` → animaciones de salida
|
|
527
|
+
|
|
528
|
+
### Overlay Animations
|
|
529
|
+
|
|
530
|
+
- **Opening**: `fade-in-0`
|
|
531
|
+
- **Closing**: `fade-out-0`
|
|
532
|
+
|
|
533
|
+
### Content Animations
|
|
534
|
+
|
|
535
|
+
- **Opening**: `fade-in-0`, `zoom-in-95`
|
|
536
|
+
- **Closing**: `fade-out-0`, `zoom-out-95`
|
|
537
|
+
- **Duration**: `200ms`
|
|
538
|
+
|
|
539
|
+
## Navegación por Teclado
|
|
540
|
+
|
|
541
|
+
- ✅ **Escape**: Cierra el dialog (previene con `onEscapeKeyDown`)
|
|
542
|
+
- ✅ **Tab**: Navega entre elementos focusables dentro del dialog
|
|
543
|
+
- ✅ **Shift+Tab**: Navegación inversa
|
|
544
|
+
- ✅ **Enter**: Activa botón/elemento enfocado
|
|
545
|
+
|
|
546
|
+
## Accesibilidad
|
|
547
|
+
|
|
548
|
+
- ✅ **ARIA**: `role="dialog"`, `aria-labelledby` (title), `aria-describedby` (description)
|
|
549
|
+
- ✅ **Focus trap**: Focus queda dentro del dialog mientras está abierto
|
|
550
|
+
- ✅ **Focus restoration**: Focus vuelve al trigger al cerrar
|
|
551
|
+
- ✅ **Screen readers**: Anuncia título, descripción, y contenido
|
|
552
|
+
- ✅ **Keyboard navigation**: Completamente navegable por teclado
|
|
553
|
+
- ✅ **Close button**: `aria-label="Close"` en botón X
|
|
554
|
+
- ✅ **Modal behavior**: Bloquea interacción con contenido externo
|
|
555
|
+
|
|
556
|
+
## Notas de Implementación
|
|
557
|
+
|
|
558
|
+
- **Basado en Radix UI**: `@radix-ui/react-dialog`
|
|
559
|
+
- **Portal rendering**: Content se renderiza en `document.body`
|
|
560
|
+
- **Overlay**: `bg-black/50`, `fixed inset-0`, `z-50`
|
|
561
|
+
- **Centrado**: `top-[50%] left-[50%]`, `translate-x-[-50%] translate-y-[-50%]`
|
|
562
|
+
- **Responsive**: `max-w-[calc(100%-2rem)]` en mobile, `sm:max-w-lg` en desktop
|
|
563
|
+
- **Close button**: XIcon automático en esquina superior derecha si `showCloseButton={true}`
|
|
564
|
+
- **Auto-close**: Cierra con Escape, clic fuera, o DialogClose
|
|
565
|
+
- **Focus management**: Primer elemento focusable recibe focus al abrir
|
|
566
|
+
- **Theme support**: Prop `theme` aplica `data-theme` al content
|
|
567
|
+
- **Z-index**: 50 para overlay y content
|
|
568
|
+
|
|
569
|
+
## Responsive Behavior
|
|
570
|
+
|
|
571
|
+
### Mobile
|
|
572
|
+
|
|
573
|
+
- `max-w-[calc(100%-2rem)]`: Margen de 1rem a cada lado
|
|
574
|
+
- `text-center`: Header centrado
|
|
575
|
+
- `flex-col-reverse`: Footer con botones apilados (Confirm arriba, Cancel abajo)
|
|
576
|
+
|
|
577
|
+
### Desktop (sm+)
|
|
578
|
+
|
|
579
|
+
- `sm:max-w-lg`: Ancho máximo 32rem
|
|
580
|
+
- `sm:text-left`: Header alineado a izquierda
|
|
581
|
+
- `sm:flex-row sm:justify-end`: Footer horizontal con botones a la derecha
|
|
582
|
+
|
|
583
|
+
## Customización de Ancho
|
|
584
|
+
|
|
585
|
+
```tsx
|
|
586
|
+
{
|
|
587
|
+
/* Small dialog */
|
|
588
|
+
}
|
|
589
|
+
<DialogContent className="sm:max-w-md">...</DialogContent>;
|
|
590
|
+
|
|
591
|
+
{
|
|
592
|
+
/* Medium (default) */
|
|
593
|
+
}
|
|
594
|
+
<DialogContent className="sm:max-w-lg">...</DialogContent>;
|
|
595
|
+
|
|
596
|
+
{
|
|
597
|
+
/* Large */
|
|
598
|
+
}
|
|
599
|
+
<DialogContent className="sm:max-w-2xl">...</DialogContent>;
|
|
600
|
+
|
|
601
|
+
{
|
|
602
|
+
/* Extra large */
|
|
603
|
+
}
|
|
604
|
+
<DialogContent className="sm:max-w-4xl">...</DialogContent>;
|
|
605
|
+
|
|
606
|
+
{
|
|
607
|
+
/* Full width with margin */
|
|
608
|
+
}
|
|
609
|
+
<DialogContent className="sm:max-w-[90vw]">...</DialogContent>;
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
## Troubleshooting
|
|
613
|
+
|
|
614
|
+
**Dialog no cierra con Escape**: Verifica que no estés previniendo evento con `onEscapeKeyDown`
|
|
615
|
+
**Dialog no cierra al hacer clic fuera**: Verifica `onPointerDownOutside` o `modal={false}`
|
|
616
|
+
**Focus no vuelve al trigger**: Asegúrate de que el trigger sigue en el DOM
|
|
617
|
+
**Scroll bloqueado después de cerrar**: Radix maneja esto automáticamente, verifica conflictos con CSS
|
|
618
|
+
**Content no centrado**: Evita `transform` CSS en elementos padre que afecten positioning
|
|
619
|
+
**Animaciones no funcionan**: Verifica que `@tailwindcss/animate` esté instalado
|
|
620
|
+
**Botón X no aparece**: Verifica `showCloseButton={true}` (default)
|
|
621
|
+
**Overlay no oscurece**: Z-index conflict, aumenta z-index del overlay
|
|
622
|
+
**Title/Description no anunciados**: Asegúrate de usar componentes DialogTitle y DialogDescription (no divs)
|
|
623
|
+
|
|
624
|
+
## Referencias
|
|
625
|
+
|
|
626
|
+
- **Radix UI Dialog**: https://www.radix-ui.com/primitives/docs/components/dialog
|
|
627
|
+
- **shadcn/ui Dialog**: https://ui.shadcn.com/docs/components/dialog
|
|
628
|
+
- **ARIA Dialog Pattern**: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
|