@ceed/ads 1.20.0 → 1.20.1-next.1

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.
Files changed (30) hide show
  1. package/dist/components/ProfileMenu/ProfileMenu.d.ts +1 -1
  2. package/dist/components/data-display/Markdown.md +832 -0
  3. package/dist/components/feedback/Dialog.md +605 -3
  4. package/dist/components/feedback/Modal.md +656 -24
  5. package/dist/components/feedback/llms.txt +1 -1
  6. package/dist/components/inputs/Autocomplete.md +734 -2
  7. package/dist/components/inputs/Calendar.md +655 -1
  8. package/dist/components/inputs/DatePicker.md +699 -3
  9. package/dist/components/inputs/DateRangePicker.md +815 -1
  10. package/dist/components/inputs/MonthPicker.md +626 -4
  11. package/dist/components/inputs/MonthRangePicker.md +682 -4
  12. package/dist/components/inputs/Select.md +600 -0
  13. package/dist/components/layout/Container.md +507 -0
  14. package/dist/components/navigation/Breadcrumbs.md +582 -0
  15. package/dist/components/navigation/IconMenuButton.md +693 -0
  16. package/dist/components/navigation/InsetDrawer.md +1150 -3
  17. package/dist/components/navigation/Link.md +526 -0
  18. package/dist/components/navigation/MenuButton.md +632 -0
  19. package/dist/components/navigation/NavigationGroup.md +401 -1
  20. package/dist/components/navigation/NavigationItem.md +311 -0
  21. package/dist/components/navigation/Navigator.md +373 -0
  22. package/dist/components/navigation/Pagination.md +521 -0
  23. package/dist/components/navigation/ProfileMenu.md +605 -0
  24. package/dist/components/navigation/Tabs.md +609 -7
  25. package/dist/components/surfaces/Accordions.md +947 -3
  26. package/dist/index.cjs +3 -1
  27. package/dist/index.js +3 -1
  28. package/dist/llms.txt +1 -1
  29. package/framer/index.js +1 -1
  30. package/package.json +3 -2
@@ -1,7 +1,9 @@
1
- # Dialog
1
+ # DialogFrame
2
2
 
3
3
  ## Introduction
4
4
 
5
+ DialogFrame is a compound component that provides a structured container for dialog content, including title, body, and action buttons. It's designed to be used within a Modal component to create consistent, accessible dialog interfaces for confirmations, forms, and informational displays. DialogFrame handles the layout and styling of dialog elements while the parent Modal manages the overlay and open/close behavior.
6
+
5
7
  ```tsx
6
8
  <DialogFrame
7
9
  title="Dialog Title"
@@ -17,12 +19,61 @@
17
19
  | fullscreen | — | — |
18
20
  | actions | — | actions |
19
21
 
20
- ## Fullscreen
22
+ > ⚠️ **Usage Warning** ⚠️
23
+ >
24
+ > Dialogs interrupt the user's workflow:
25
+ >
26
+ > - **Confirmations only**: Use dialogs for important decisions that need confirmation
27
+ > - **Keep it brief**: Dialog content should be scannable and actionable
28
+ > - **Consider alternatives**: Use Toast for feedback, Alert for inline messages
29
+ > - **Wrap with Modal**: DialogFrame should be used inside a Modal component for proper behavior
30
+
31
+ ## Usage
32
+
33
+ ```tsx
34
+ import { Modal, DialogFrame, Button } from '@ceed/ads';
35
+
36
+ function ConfirmationDialog({ open, onClose, onConfirm }) {
37
+ return (
38
+ <Modal open={open} onClose={onClose}>
39
+ <DialogFrame
40
+ title="Confirm Action"
41
+ actions={
42
+ <>
43
+ <Button variant="plain" color="neutral" onClick={onClose}>
44
+ Cancel
45
+ </Button>
46
+ <Button onClick={onConfirm}>
47
+ Confirm
48
+ </Button>
49
+ </>
50
+ }
51
+ >
52
+ Are you sure you want to proceed with this action?
53
+ </DialogFrame>
54
+ </Modal>
55
+ );
56
+ }
57
+ ```
58
+
59
+ ## Examples
60
+
61
+ ### Playground
62
+
63
+ Interactive example with title, content, and action buttons.
21
64
 
22
65
  ```tsx
23
- import { Dialog } from '@ceed/ads';
66
+ <DialogFrame
67
+ title="Dialog Title"
68
+ children="Dialog Content"
69
+ actions={actions}
70
+ />
24
71
  ```
25
72
 
73
+ ### Fullscreen
74
+
75
+ Fullscreen mode for complex content or mobile views.
76
+
26
77
  ```tsx
27
78
  <DialogFrame
28
79
  title="Dialog Title"
@@ -31,3 +82,554 @@ import { Dialog } from '@ceed/ads';
31
82
  fullscreen
32
83
  />
33
84
  ```
85
+
86
+ ### With Input (KeyDown Handling)
87
+
88
+ Dialog with form inputs and keyboard event handling.
89
+
90
+ ```tsx
91
+ <DialogFrame {...args} title="Dialog Title" actions={<Button variant="plain">Action</Button>}>
92
+ Dialog Content
93
+ <Input />
94
+ </DialogFrame>
95
+ ```
96
+
97
+ ## When to Use
98
+
99
+ ### ✅ Good Use Cases
100
+
101
+ - **Confirmations**: Delete, submit, or irreversible action confirmations
102
+ - **Simple forms**: Login, quick input, or single-field forms
103
+ - **Alerts**: Important information that requires acknowledgment
104
+ - **Choices**: Binary or limited-option decisions
105
+ - **Terms acceptance**: Legal agreements that need explicit consent
106
+
107
+ ### ❌ When Not to Use
108
+
109
+ - **Complex forms**: Use a dedicated page for multi-step forms
110
+ - **Notifications**: Use Toast for non-blocking feedback
111
+ - **Inline messages**: Use Alert for contextual information
112
+ - **Frequent interactions**: Don't interrupt common workflows
113
+ - **Large content**: Use a page or InsetDrawer for lengthy content
114
+
115
+ ## Common Use Cases
116
+
117
+ ### Delete Confirmation
118
+
119
+ ```tsx
120
+ function DeleteConfirmation({ itemName, open, onClose, onDelete }) {
121
+ return (
122
+ <Modal open={open} onClose={onClose}>
123
+ <DialogFrame
124
+ title="Delete Item"
125
+ actions={
126
+ <>
127
+ <Button variant="plain" color="neutral" onClick={onClose}>
128
+ Cancel
129
+ </Button>
130
+ <Button color="danger" onClick={onDelete}>
131
+ Delete
132
+ </Button>
133
+ </>
134
+ }
135
+ >
136
+ <Typography>
137
+ Are you sure you want to delete <strong>{itemName}</strong>?
138
+ </Typography>
139
+ <Typography level="body-sm" color="neutral" sx={{ mt: 1 }}>
140
+ This action cannot be undone.
141
+ </Typography>
142
+ </DialogFrame>
143
+ </Modal>
144
+ );
145
+ }
146
+ ```
147
+
148
+ ### Form Dialog
149
+
150
+ ```tsx
151
+ function QuickAddDialog({ open, onClose, onSubmit }) {
152
+ const [name, setName] = useState('');
153
+ const [email, setEmail] = useState('');
154
+
155
+ const handleSubmit = () => {
156
+ onSubmit({ name, email });
157
+ setName('');
158
+ setEmail('');
159
+ onClose();
160
+ };
161
+
162
+ return (
163
+ <Modal open={open} onClose={onClose}>
164
+ <DialogFrame
165
+ title="Add New User"
166
+ actions={
167
+ <>
168
+ <Button variant="plain" color="neutral" onClick={onClose}>
169
+ Cancel
170
+ </Button>
171
+ <Button onClick={handleSubmit} disabled={!name || !email}>
172
+ Add User
173
+ </Button>
174
+ </>
175
+ }
176
+ >
177
+ <Stack gap={2}>
178
+ <FormControl>
179
+ <FormLabel>Name</FormLabel>
180
+ <Input
181
+ value={name}
182
+ onChange={(e) => setName(e.target.value)}
183
+ placeholder="Enter name"
184
+ autoFocus
185
+ />
186
+ </FormControl>
187
+ <FormControl>
188
+ <FormLabel>Email</FormLabel>
189
+ <Input
190
+ type="email"
191
+ value={email}
192
+ onChange={(e) => setEmail(e.target.value)}
193
+ placeholder="Enter email"
194
+ />
195
+ </FormControl>
196
+ </Stack>
197
+ </DialogFrame>
198
+ </Modal>
199
+ );
200
+ }
201
+ ```
202
+
203
+ ### Unsaved Changes Warning
204
+
205
+ ```tsx
206
+ function UnsavedChangesDialog({ open, onClose, onDiscard, onSave }) {
207
+ return (
208
+ <Modal open={open} onClose={onClose}>
209
+ <DialogFrame
210
+ title="Unsaved Changes"
211
+ actions={
212
+ <>
213
+ <Button variant="plain" color="neutral" onClick={onClose}>
214
+ Cancel
215
+ </Button>
216
+ <Button variant="outlined" color="danger" onClick={onDiscard}>
217
+ Discard
218
+ </Button>
219
+ <Button onClick={onSave}>
220
+ Save Changes
221
+ </Button>
222
+ </>
223
+ }
224
+ >
225
+ <Typography>
226
+ You have unsaved changes. Would you like to save them before leaving?
227
+ </Typography>
228
+ </DialogFrame>
229
+ </Modal>
230
+ );
231
+ }
232
+ ```
233
+
234
+ ### Information Dialog
235
+
236
+ ```tsx
237
+ function InfoDialog({ open, onClose, title, message }) {
238
+ return (
239
+ <Modal open={open} onClose={onClose}>
240
+ <DialogFrame
241
+ title={title}
242
+ actions={
243
+ <Button onClick={onClose}>
244
+ Got it
245
+ </Button>
246
+ }
247
+ >
248
+ <Typography>{message}</Typography>
249
+ </DialogFrame>
250
+ </Modal>
251
+ );
252
+ }
253
+ ```
254
+
255
+ ### Terms Acceptance
256
+
257
+ ```tsx
258
+ function TermsDialog({ open, onClose, onAccept }) {
259
+ const [accepted, setAccepted] = useState(false);
260
+
261
+ return (
262
+ <Modal open={open} onClose={onClose}>
263
+ <DialogFrame
264
+ title="Terms and Conditions"
265
+ actions={
266
+ <>
267
+ <Button variant="plain" color="neutral" onClick={onClose}>
268
+ Decline
269
+ </Button>
270
+ <Button onClick={onAccept} disabled={!accepted}>
271
+ Accept
272
+ </Button>
273
+ </>
274
+ }
275
+ >
276
+ <Box sx={{ maxHeight: 300, overflow: 'auto', mb: 2 }}>
277
+ <Typography level="body-sm">
278
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit...
279
+ {/* Terms content */}
280
+ </Typography>
281
+ </Box>
282
+ <Checkbox
283
+ label="I have read and agree to the terms and conditions"
284
+ checked={accepted}
285
+ onChange={(e) => setAccepted(e.target.checked)}
286
+ />
287
+ </DialogFrame>
288
+ </Modal>
289
+ );
290
+ }
291
+ ```
292
+
293
+ ### Loading State Dialog
294
+
295
+ ```tsx
296
+ function ProcessingDialog({ open, status, onClose }) {
297
+ const isProcessing = status === 'processing';
298
+ const isSuccess = status === 'success';
299
+ const isError = status === 'error';
300
+
301
+ return (
302
+ <Modal open={open} onClose={isProcessing ? undefined : onClose}>
303
+ <DialogFrame
304
+ title={
305
+ isProcessing ? 'Processing...' :
306
+ isSuccess ? 'Success!' :
307
+ 'Error'
308
+ }
309
+ actions={
310
+ !isProcessing && (
311
+ <Button onClick={onClose}>
312
+ {isSuccess ? 'Done' : 'Try Again'}
313
+ </Button>
314
+ )
315
+ }
316
+ >
317
+ <Box sx={{ textAlign: 'center', py: 2 }}>
318
+ {isProcessing && <CircularProgress />}
319
+ {isSuccess && <CheckCircleIcon color="success" sx={{ fontSize: 48 }} />}
320
+ {isError && <ErrorIcon color="error" sx={{ fontSize: 48 }} />}
321
+ <Typography sx={{ mt: 2 }}>
322
+ {isProcessing && 'Please wait while we process your request...'}
323
+ {isSuccess && 'Your request has been processed successfully.'}
324
+ {isError && 'Something went wrong. Please try again.'}
325
+ </Typography>
326
+ </Box>
327
+ </DialogFrame>
328
+ </Modal>
329
+ );
330
+ }
331
+ ```
332
+
333
+ ### Selection Dialog
334
+
335
+ ```tsx
336
+ function SelectOptionDialog({ open, onClose, options, onSelect }) {
337
+ return (
338
+ <Modal open={open} onClose={onClose}>
339
+ <DialogFrame
340
+ title="Select an Option"
341
+ actions={
342
+ <Button variant="plain" color="neutral" onClick={onClose}>
343
+ Cancel
344
+ </Button>
345
+ }
346
+ >
347
+ <List>
348
+ {options.map((option) => (
349
+ <ListItem key={option.value}>
350
+ <ListItemButton
351
+ onClick={() => {
352
+ onSelect(option.value);
353
+ onClose();
354
+ }}
355
+ >
356
+ <ListItemDecorator>{option.icon}</ListItemDecorator>
357
+ <ListItemContent>
358
+ <Typography level="title-sm">{option.label}</Typography>
359
+ <Typography level="body-xs">{option.description}</Typography>
360
+ </ListItemContent>
361
+ </ListItemButton>
362
+ </ListItem>
363
+ ))}
364
+ </List>
365
+ </DialogFrame>
366
+ </Modal>
367
+ );
368
+ }
369
+ ```
370
+
371
+ ## Props and Customization
372
+
373
+ ### Key Props
374
+
375
+ | Prop | Type | Default | Description |
376
+ | ------------ | -------------------------------- | ------- | -------------------------------------- |
377
+ | `title` | `string` | - | Dialog title displayed in the header |
378
+ | `children` | `ReactNode` | - | Dialog body content |
379
+ | `actions` | `ReactNode` | - | Action buttons displayed in the footer |
380
+ | `fullscreen` | `boolean` | `false` | Enable fullscreen mode |
381
+ | `onKeyDown` | `(event: KeyboardEvent) => void` | - | Keyboard event handler |
382
+
383
+ ### Structure
384
+
385
+ DialogFrame provides a three-part layout:
386
+
387
+ ```tsx
388
+ <DialogFrame
389
+ title="Header" // Top: Title section
390
+ actions={...} // Bottom: Action buttons
391
+ >
392
+ {/* Middle: Content area */}
393
+ </DialogFrame>
394
+ ```
395
+
396
+ ### With Modal
397
+
398
+ DialogFrame should be wrapped in Modal for proper behavior:
399
+
400
+ ```tsx
401
+ <Modal open={open} onClose={onClose}>
402
+ <DialogFrame title="Title" actions={actions}>
403
+ Content
404
+ </DialogFrame>
405
+ </Modal>
406
+ ```
407
+
408
+ ### Action Button Patterns
409
+
410
+ ```tsx
411
+ // Confirmation (Cancel + Confirm)
412
+ <DialogFrame
413
+ actions={
414
+ <>
415
+ <Button variant="plain" color="neutral" onClick={onClose}>
416
+ Cancel
417
+ </Button>
418
+ <Button onClick={onConfirm}>Confirm</Button>
419
+ </>
420
+ }
421
+ />
422
+
423
+ // Destructive action
424
+ <DialogFrame
425
+ actions={
426
+ <>
427
+ <Button variant="plain" color="neutral" onClick={onClose}>
428
+ Cancel
429
+ </Button>
430
+ <Button color="danger" onClick={onDelete}>Delete</Button>
431
+ </>
432
+ }
433
+ />
434
+
435
+ // Single action (acknowledgment)
436
+ <DialogFrame
437
+ actions={
438
+ <Button onClick={onClose}>OK</Button>
439
+ }
440
+ />
441
+
442
+ // Three options
443
+ <DialogFrame
444
+ actions={
445
+ <>
446
+ <Button variant="plain" color="neutral" onClick={onCancel}>Cancel</Button>
447
+ <Button variant="outlined" onClick={onSecondary}>Don't Save</Button>
448
+ <Button onClick={onPrimary}>Save</Button>
449
+ </>
450
+ }
451
+ />
452
+ ```
453
+
454
+ ### Fullscreen Mode
455
+
456
+ ```tsx
457
+ // Fullscreen for complex content or mobile
458
+ <Modal open={open} onClose={onClose}>
459
+ <DialogFrame fullscreen title="Edit Profile">
460
+ <Box sx={{ p: 2 }}>
461
+ {/* Large form or content */}
462
+ </Box>
463
+ </DialogFrame>
464
+ </Modal>
465
+ ```
466
+
467
+ ## Accessibility
468
+
469
+ DialogFrame inherits accessibility features from Modal:
470
+
471
+ ### ARIA Attributes
472
+
473
+ - Dialog has `role="dialog"` via Modal
474
+ - Title provides `aria-labelledby`
475
+ - Focus is trapped within the dialog
476
+ - Background is marked as `aria-hidden`
477
+
478
+ ### Keyboard Navigation
479
+
480
+ - **Escape**: Close the dialog (via Modal)
481
+ - **Tab**: Navigate between focusable elements
482
+ - **Enter**: Activate focused button
483
+
484
+ ### Focus Management
485
+
486
+ ```tsx
487
+ // Auto-focus first input
488
+ <DialogFrame title="Add Item">
489
+ <Input autoFocus placeholder="Item name" />
490
+ </DialogFrame>
491
+
492
+ // Focus returns to trigger when closed
493
+ <Button onClick={() => setOpen(true)}>Open Dialog</Button>
494
+ <Modal open={open} onClose={() => setOpen(false)}>
495
+ <DialogFrame>...</DialogFrame>
496
+ </Modal>
497
+ ```
498
+
499
+ ### Screen Reader Support
500
+
501
+ ```tsx
502
+ // Title provides context
503
+ <DialogFrame title="Confirm Deletion">
504
+ {/* Content is read after title */}
505
+ </DialogFrame>
506
+ ```
507
+
508
+ ## Best Practices
509
+
510
+ ### ✅ Do
511
+
512
+ 1. **Use clear, action-oriented titles**: Tell users what they're confirming
513
+
514
+ ```tsx
515
+ // ✅ Good: Specific title
516
+ <DialogFrame title="Delete Account" />
517
+ <DialogFrame title="Save Changes" />
518
+ ```
519
+
520
+ 2. **Provide clear button labels**: Use verbs that describe the action
521
+
522
+ ```tsx
523
+ // ✅ Good: Clear action buttons
524
+ <Button color="danger">Delete</Button>
525
+ <Button>Save Changes</Button>
526
+ ```
527
+
528
+ 3. **Keep content concise**: Users should quickly understand and decide
529
+
530
+ ```tsx
531
+ // ✅ Good: Brief, scannable content
532
+ <DialogFrame title="Delete Project">
533
+ <Typography>
534
+ This will permanently delete the project and all its data.
535
+ </Typography>
536
+ </DialogFrame>
537
+ ```
538
+
539
+ 4. **Always provide a cancel option**: Let users safely exit
540
+
541
+ ```tsx
542
+ // ✅ Good: Cancel button available
543
+ <DialogFrame
544
+ actions={
545
+ <>
546
+ <Button variant="plain" color="neutral" onClick={onClose}>
547
+ Cancel
548
+ </Button>
549
+ <Button onClick={onConfirm}>Confirm</Button>
550
+ </>
551
+ }
552
+ />
553
+ ```
554
+
555
+ ### ❌ Don't
556
+
557
+ 1. **Don't use for notifications**: Use Toast instead
558
+
559
+ ```tsx
560
+ // ❌ Bad: Dialog for simple feedback
561
+ <DialogFrame title="Success">
562
+ <Typography>Item saved!</Typography>
563
+ </DialogFrame>
564
+
565
+ // ✅ Good: Use Toast
566
+ showToast({ message: 'Item saved!' });
567
+ ```
568
+
569
+ 2. **Don't include too much content**: Use a page for complex forms
570
+
571
+ ```tsx
572
+ // ❌ Bad: Complex form in dialog
573
+ <DialogFrame title="Create Account">
574
+ {/* 20+ form fields */}
575
+ </DialogFrame>
576
+ ```
577
+
578
+ 3. **Don't use vague button labels**: Be specific about actions
579
+
580
+ ```tsx
581
+ // ❌ Bad: Unclear actions
582
+ <Button>OK</Button>
583
+ <Button>Cancel</Button>
584
+
585
+ // ✅ Good: Clear actions
586
+ <Button>Delete Account</Button>
587
+ <Button variant="plain">Keep Account</Button>
588
+ ```
589
+
590
+ 4. **Don't block critical workflows**: Important features should be accessible
591
+
592
+ ## Performance Considerations
593
+
594
+ ### Lazy Load Dialog Content
595
+
596
+ For dialogs with heavy content:
597
+
598
+ ```tsx
599
+ function HeavyDialog({ open, onClose }) {
600
+ return (
601
+ <Modal open={open} onClose={onClose}>
602
+ <DialogFrame title="Data Preview">
603
+ {open && <HeavyDataComponent />}
604
+ </DialogFrame>
605
+ </Modal>
606
+ );
607
+ }
608
+ ```
609
+
610
+ ### Memoize Handlers
611
+
612
+ ```tsx
613
+ const handleConfirm = useCallback(() => {
614
+ performAction();
615
+ onClose();
616
+ }, [performAction, onClose]);
617
+
618
+ const handleCancel = useCallback(() => {
619
+ onClose();
620
+ }, [onClose]);
621
+ ```
622
+
623
+ ### Conditionally Render
624
+
625
+ Unmount dialog completely when not needed:
626
+
627
+ ```tsx
628
+ {open && (
629
+ <Modal open={open} onClose={onClose}>
630
+ <DialogFrame>...</DialogFrame>
631
+ </Modal>
632
+ )}
633
+ ```
634
+
635
+ DialogFrame provides a consistent structure for dialog content. Combine it with Modal for proper overlay behavior, keep content concise and actionable, and always provide clear options for users to proceed or cancel.