@ceed/ads 1.29.1 → 1.30.0-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 (62) hide show
  1. package/dist/components/CurrencyInput/CurrencyInput.d.ts +1 -1
  2. package/dist/components/CurrencyInput/hooks/use-currency-setting.d.ts +2 -2
  3. package/dist/components/ProfileMenu/ProfileMenu.d.ts +1 -1
  4. package/dist/components/SearchBar/SearchBar.d.ts +21 -0
  5. package/dist/components/SearchBar/index.d.ts +3 -0
  6. package/dist/components/data-display/Badge.md +39 -71
  7. package/dist/components/data-display/DataTable.md +1 -1
  8. package/dist/components/data-display/InfoSign.md +98 -74
  9. package/dist/components/data-display/Typography.md +97 -363
  10. package/dist/components/feedback/Dialog.md +62 -76
  11. package/dist/components/feedback/Modal.md +44 -259
  12. package/dist/components/feedback/llms.txt +0 -2
  13. package/dist/components/index.d.ts +2 -0
  14. package/dist/components/inputs/Autocomplete.md +107 -356
  15. package/dist/components/inputs/ButtonGroup.md +106 -115
  16. package/dist/components/inputs/Calendar.md +459 -98
  17. package/dist/components/inputs/CurrencyInput.md +5 -183
  18. package/dist/components/inputs/DatePicker.md +431 -108
  19. package/dist/components/inputs/DateRangePicker.md +492 -131
  20. package/dist/components/inputs/FilterMenu.md +19 -169
  21. package/dist/components/inputs/FilterableCheckboxGroup.md +23 -123
  22. package/dist/components/inputs/IconButton.md +88 -137
  23. package/dist/components/inputs/Input.md +0 -5
  24. package/dist/components/inputs/MonthPicker.md +422 -95
  25. package/dist/components/inputs/MonthRangePicker.md +466 -89
  26. package/dist/components/inputs/PercentageInput.md +16 -185
  27. package/dist/components/inputs/RadioButton.md +35 -163
  28. package/dist/components/inputs/RadioTileGroup.md +61 -150
  29. package/dist/components/inputs/SearchBar.md +44 -0
  30. package/dist/components/inputs/Select.md +326 -222
  31. package/dist/components/inputs/Switch.md +376 -136
  32. package/dist/components/inputs/Textarea.md +10 -213
  33. package/dist/components/inputs/Uploader/Uploader.md +66 -145
  34. package/dist/components/inputs/llms.txt +1 -3
  35. package/dist/components/navigation/Breadcrumbs.md +322 -80
  36. package/dist/components/navigation/Dropdown.md +221 -92
  37. package/dist/components/navigation/IconMenuButton.md +502 -40
  38. package/dist/components/navigation/InsetDrawer.md +738 -68
  39. package/dist/components/navigation/Link.md +298 -39
  40. package/dist/components/navigation/Menu.md +285 -92
  41. package/dist/components/navigation/MenuButton.md +448 -55
  42. package/dist/components/navigation/Pagination.md +338 -47
  43. package/dist/components/navigation/ProfileMenu.md +268 -45
  44. package/dist/components/navigation/Stepper.md +28 -160
  45. package/dist/components/navigation/Tabs.md +316 -57
  46. package/dist/components/surfaces/Sheet.md +334 -151
  47. package/dist/index.browser.js +15 -13
  48. package/dist/index.browser.js.map +4 -4
  49. package/dist/index.cjs +289 -288
  50. package/dist/index.d.ts +1 -1
  51. package/dist/index.js +426 -369
  52. package/dist/llms.txt +1 -8
  53. package/framer/index.js +1 -1
  54. package/package.json +16 -15
  55. package/dist/chunks/rehype-accent-FZRUD7VI.js +0 -39
  56. package/dist/components/feedback/CircularProgress.md +0 -257
  57. package/dist/components/feedback/Skeleton.md +0 -280
  58. package/dist/components/inputs/FormControl.md +0 -361
  59. package/dist/components/inputs/RadioList.md +0 -241
  60. package/dist/components/inputs/Slider.md +0 -334
  61. package/dist/guides/ThemeProvider.md +0 -116
  62. package/dist/guides/llms.txt +0 -9
@@ -2,9 +2,7 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- ProfileMenu is a user account dropdown component that displays the current user's profile information and provides quick access to account-related actions. It combines an avatar trigger button with a dropdown menu containing the user's name, an optional badge (chip), caption text (such as email), and customizable menu items.
6
-
7
- ProfileMenu is typically placed in the application header or top navigation bar. It supports both controlled and uncontrolled open state, avatar image or auto-generated initials, multiple size variants, and flexible menu item configuration.
5
+ ProfileMenu is a user account dropdown component that displays the current user's profile information and provides quick access to account-related actions. It combines an avatar button with a dropdown menu containing the user's name, optional badge (chip), caption (like email), and customizable menu items. ProfileMenu is typically placed in the header or navigation area of an application.
8
6
 
9
7
  ```tsx
10
8
  <ProfileMenu
@@ -54,11 +52,11 @@ function Header() {
54
52
  }
55
53
  ```
56
54
 
57
- ## Profile Variations
55
+ ## Examples
58
56
 
59
57
  ### Default
60
58
 
61
- ProfileMenu with full profile information including name, chip badge, and caption.
59
+ ProfileMenu with full profile information including name, chip, and caption.
62
60
 
63
61
  ```tsx
64
62
  <ProfileMenu
@@ -83,7 +81,7 @@ ProfileMenu with full profile information including name, chip badge, and captio
83
81
 
84
82
  ### Without Caption
85
83
 
86
- Profile showing only the name and chip badge, without a secondary caption line.
84
+ Profile showing only the name and chip badge.
87
85
 
88
86
  ```tsx
89
87
  <ProfileMenu
@@ -107,7 +105,7 @@ Profile showing only the name and chip badge, without a secondary caption line.
107
105
 
108
106
  ### Without Chip
109
107
 
110
- Profile showing the name and caption, without a badge chip.
108
+ Profile showing name and caption without a badge.
111
109
 
112
110
  ```tsx
113
111
  <ProfileMenu
@@ -131,7 +129,7 @@ Profile showing the name and caption, without a badge chip.
131
129
 
132
130
  ### Only Name
133
131
 
134
- Minimal profile display with just the user's name. Useful for compact layouts where additional context is not needed.
132
+ Minimal profile with just the user's name.
135
133
 
136
134
  ```tsx
137
135
  <ProfileMenu
@@ -154,7 +152,7 @@ Minimal profile display with just the user's name. Useful for compact layouts wh
154
152
 
155
153
  ### Without Menu Items
156
154
 
157
- Profile card without any action menu items. The dropdown displays only the user information.
155
+ Profile card without any menu actions.
158
156
 
159
157
  ```tsx
160
158
  <ProfileMenu
@@ -168,9 +166,9 @@ Profile card without any action menu items. The dropdown displays only the user
168
166
  />
169
167
  ```
170
168
 
171
- ## Sizes
169
+ ### Sizes
172
170
 
173
- ProfileMenu supports `md` (default) and `sm` size variants for use in different layout densities.
171
+ ProfileMenu supports different sizes for various layouts.
174
172
 
175
173
  ```tsx
176
174
  <Stack direction="row" gap="150px">
@@ -205,11 +203,9 @@ ProfileMenu supports `md` (default) and `sm` size variants for use in different
205
203
  </Stack>
206
204
  ```
207
205
 
208
- ## Avatar
209
-
210
206
  ### With Profile Image
211
207
 
212
- When a user has a profile picture, pass the `image` property with `src` and `alt`. The image replaces the auto-generated initials.
208
+ Display a custom avatar image instead of generated initials.
213
209
 
214
210
  ```tsx
215
211
  <ProfileMenu
@@ -237,7 +233,7 @@ When a user has a profile picture, pass the `image` property with `src` and `alt
237
233
 
238
234
  ### With Korean Name
239
235
 
240
- ProfileMenu automatically generates initials from various name formats, including Korean names.
236
+ ProfileMenu automatically generates initials from various name formats.
241
237
 
242
238
  ```tsx
243
239
  <>
@@ -254,11 +250,9 @@ ProfileMenu automatically generates initials from various name formats, includin
254
250
  </>
255
251
  ```
256
252
 
257
- ## Controlled vs Uncontrolled
258
-
259
253
  ### Controlled
260
254
 
261
- Use the `open` and `onOpenChange` props to control the menu's open state programmatically.
255
+ Programmatically control the menu's open state.
262
256
 
263
257
  ```tsx
264
258
  <ProfileMenu {...args} open={open} onOpenChange={setOpen} />
@@ -266,7 +260,7 @@ Use the `open` and `onOpenChange` props to control the menu's open state program
266
260
 
267
261
  ### Uncontrolled
268
262
 
269
- Use `defaultOpen` to set the initial state, then let the component manage its own open/close behavior internally.
263
+ Let the component manage its own open state internally.
270
264
 
271
265
  ```tsx
272
266
  <ProfileMenu
@@ -289,6 +283,24 @@ Use `defaultOpen` to set the initial state, then let the component manage its ow
289
283
  />
290
284
  ```
291
285
 
286
+ ## When to Use
287
+
288
+ ### ✅ Good Use Cases
289
+
290
+ - **Application header**: Display current user and account actions
291
+ - **Admin dashboards**: Quick access to user settings and logout
292
+ - **Multi-user applications**: Show which account is active
293
+ - **Settings access**: Provide shortcuts to profile and preferences
294
+ - **Authentication flows**: Display logged-in user with sign-out option
295
+
296
+ ### ❌ When Not to Use
297
+
298
+ - **Anonymous users**: Don't show ProfileMenu for non-authenticated users
299
+ - **Simple navigation**: Use regular dropdown for non-profile menus
300
+ - **Primary actions**: Critical actions belong in the main UI, not hidden in profile
301
+ - **Complex forms**: Don't put forms or heavy content in the dropdown
302
+ - **Mobile navigation**: Consider slide-out drawer or full-screen menu instead
303
+
292
304
  ## Common Use Cases
293
305
 
294
306
  ### Header Navigation
@@ -298,7 +310,7 @@ function AppHeader() {
298
310
  const { user, signOut } = useAuth();
299
311
 
300
312
  return (
301
- <header style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
313
+ <header>
302
314
  <Logo />
303
315
  <Navigation />
304
316
  <ProfileMenu
@@ -311,6 +323,7 @@ function AppHeader() {
311
323
  menuItems={[
312
324
  { label: 'My Profile', onClick: () => navigate('/profile') },
313
325
  { label: 'Account Settings', onClick: () => navigate('/settings') },
326
+ { label: 'Help & Support', onClick: () => window.open('/help') },
314
327
  { label: 'Sign Out', onClick: signOut },
315
328
  ]}
316
329
  />
@@ -322,19 +335,26 @@ function AppHeader() {
322
335
  ### Multi-Role User
323
336
 
324
337
  ```tsx
325
- function RoleBasedProfileMenu({ user, currentRole, switchRole, signOut }) {
338
+ function RoleBasedProfileMenu({ user, currentRole, switchRole }) {
326
339
  const menuItems = [
327
340
  { label: 'My Profile', onClick: () => navigate('/profile') },
328
341
  { label: 'Settings', onClick: () => navigate('/settings') },
329
- ...user.roles
330
- .filter((role) => role !== currentRole)
331
- .map((role) => ({
332
- label: `Switch to ${role}`,
333
- onClick: () => switchRole(role),
334
- })),
335
- { label: 'Sign Out', onClick: signOut },
336
342
  ];
337
343
 
344
+ // Add role switching if user has multiple roles
345
+ if (user.roles.length > 1) {
346
+ user.roles
347
+ .filter((role) => role !== currentRole)
348
+ .forEach((role) => {
349
+ menuItems.push({
350
+ label: `Switch to ${role}`,
351
+ onClick: () => switchRole(role),
352
+ });
353
+ });
354
+ }
355
+
356
+ menuItems.push({ label: 'Sign Out', onClick: () => signOut() });
357
+
338
358
  return (
339
359
  <ProfileMenu
340
360
  profile={{
@@ -371,46 +391,249 @@ function OrgProfileMenu({ user, organization }) {
371
391
  }
372
392
  ```
373
393
 
394
+ ### With Custom Initial Generation
395
+
396
+ ```tsx
397
+ function CustomInitialsProfileMenu({ user }) {
398
+ // Custom function to generate initials
399
+ const getInitial = (name) => {
400
+ // For Korean names, use first character
401
+ if (/[\uAC00-\uD7AF]/.test(name)) {
402
+ return name.charAt(0);
403
+ }
404
+ // For English names, use first letters of first and last name
405
+ const parts = name.split(' ');
406
+ if (parts.length >= 2) {
407
+ return `${parts[0][0]}${parts[parts.length - 1][0]}`;
408
+ }
409
+ return name.substring(0, 2).toUpperCase();
410
+ };
411
+
412
+ return (
413
+ <ProfileMenu
414
+ profile={{
415
+ name: user.name,
416
+ caption: user.email,
417
+ }}
418
+ menuItems={[
419
+ { label: 'Profile', onClick: () => navigate('/profile') },
420
+ { label: 'Sign Out', onClick: () => signOut() },
421
+ ]}
422
+ getInitial={getInitial}
423
+ />
424
+ );
425
+ }
426
+ ```
427
+
428
+ ## Props and Customization
429
+
430
+ ### Key Props
431
+
432
+ | Prop | Type | Default | Description |
433
+ | -------------- | -------------------------- | ------- | ---------------------------------- |
434
+ | `profile` | `Profile` | - | User profile information |
435
+ | `menuItems` | `MenuItem[]` | `[]` | Array of menu actions |
436
+ | `open` | `boolean` | - | Controlled open state |
437
+ | `defaultOpen` | `boolean` | `false` | Default open state (uncontrolled) |
438
+ | `onOpenChange` | `(open: boolean) => void` | - | Callback when open state changes |
439
+ | `size` | `'sm' \| 'md'` | `'md'` | Size variant |
440
+ | `getInitial` | `(name: string) => string` | - | Custom initial generation function |
441
+
442
+ ### Profile Type
443
+
444
+ ```tsx
445
+ interface Profile {
446
+ name: string; // User's display name (required)
447
+ caption?: string; // Secondary text (email, role description)
448
+ chip?: string; // Badge text (role, status)
449
+ image?: {
450
+ src: string; // Avatar image URL
451
+ alt: string; // Alt text for accessibility
452
+ };
453
+ }
454
+ ```
455
+
456
+ ### MenuItem Type
457
+
458
+ ```tsx
459
+ interface MenuItem {
460
+ label: string; // Menu item text
461
+ onClick?: () => void; // Click handler
462
+ // Plus any other MenuItem props from Joy UI
463
+ }
464
+ ```
465
+
466
+ ### Controlled vs Uncontrolled
467
+
468
+ ```tsx
469
+ // Uncontrolled - component manages state
470
+ <ProfileMenu
471
+ defaultOpen={false}
472
+ profile={profile}
473
+ menuItems={menuItems}
474
+ />
475
+
476
+ // Controlled - you manage state
477
+ const [open, setOpen] = useState(false);
478
+ <ProfileMenu
479
+ open={open}
480
+ onOpenChange={setOpen}
481
+ profile={profile}
482
+ menuItems={menuItems}
483
+ />
484
+ ```
485
+
486
+ ## Accessibility
487
+
488
+ ProfileMenu includes built-in accessibility features:
489
+
490
+ ### ARIA Attributes
491
+
492
+ - Button has proper `aria-haspopup` and `aria-expanded` attributes
493
+ - Menu uses `role="menu"` with proper `role="menuitem"` for items
494
+ - Focus management when opening and closing
495
+
496
+ ### Keyboard Navigation
497
+
498
+ - **Tab**: Focus the profile button
499
+ - **Enter/Space**: Open the menu
500
+ - **Arrow Down**: Move to next menu item
501
+ - **Arrow Up**: Move to previous menu item
502
+ - **Enter**: Activate focused menu item
503
+ - **Escape**: Close the menu
504
+
505
+ ### Screen Reader Support
506
+
507
+ ```tsx
508
+ // Avatar announces the user name
509
+ <ProfileMenu
510
+ profile={{
511
+ name: 'John Doe', // Avatar reads "JD, John Doe"
512
+ image: { src: '...', alt: 'John Doe profile picture' },
513
+ }}
514
+ />
515
+ ```
516
+
517
+ ### Focus Management
518
+
519
+ - Focus moves to first menu item when opened
520
+ - Focus returns to button when menu closes
521
+ - Click outside closes menu and returns focus
522
+
374
523
  ## Best Practices
375
524
 
376
- 1. **Always include essential actions**: At minimum, provide access to profile viewing and sign-out.
525
+ ### Do
526
+
527
+ 1. **Include essential actions**: Always include profile and sign-out options
377
528
 
378
529
  ```tsx
379
- // ✅ Good: Essential menu items present
530
+ // ✅ Good: Essential menu items
380
531
  <ProfileMenu
381
532
  menuItems={[
382
533
  { label: 'Profile', onClick: handleProfile },
534
+ { label: 'Settings', onClick: handleSettings },
383
535
  { label: 'Sign Out', onClick: handleSignOut },
384
536
  ]}
385
537
  />
386
-
387
- // ❌ Bad: Missing sign-out option
388
- <ProfileMenu menuItems={[{ label: 'Profile', onClick: handleProfile }]} />
389
538
  ```
390
539
 
391
- 2. **Show user context**: Use the `chip` prop to display the user's current role or status so they know which account context they are operating in.
540
+ 2. **Show user context**: Display role or organization context in the chip
392
541
 
393
542
  ```tsx
394
543
  // ✅ Good: Clear user context
395
544
  <ProfileMenu
396
- profile={{ name: 'Jane Smith', caption: 'jane@company.com', chip: 'Admin' }}
545
+ profile={{
546
+ name: 'Jane Smith',
547
+ caption: 'jane@company.com',
548
+ chip: 'Admin', // Shows current role
549
+ }}
397
550
  />
398
551
  ```
399
552
 
400
- 3. **Keep menu items concise**: Limit the number of menu items to 5-7 maximum. Move less common actions to a dedicated settings page.
553
+ 3. **Use descriptive labels**: Menu items should clearly describe actions
554
+
555
+ 4. **Provide avatar images**: When available, show actual profile photos
556
+
557
+ ### ❌ Don't
558
+
559
+ 1. **Don't overload with items**: Keep menu items to 5-7 maximum
401
560
 
402
561
  ```tsx
403
- // ❌ Bad: Too many items in the dropdown
404
- <ProfileMenu menuItems={[item1, item2, item3, item4, item5, item6, item7, item8, item9]} />
562
+ // ❌ Bad: Too many items
563
+ <ProfileMenu
564
+ menuItems={[
565
+ { label: 'Profile' },
566
+ { label: 'Settings' },
567
+ { label: 'Billing' },
568
+ { label: 'Team' },
569
+ { label: 'Integrations' },
570
+ { label: 'API Keys' },
571
+ { label: 'Audit Log' },
572
+ { label: 'Help' },
573
+ { label: 'Sign Out' },
574
+ ]}
575
+ />
405
576
  ```
406
577
 
407
- 4. **Provide avatar images when available**: Real profile photos help users quickly identify the active account, especially in multi-user or shared environments.
578
+ 2. **Don't hide critical actions**: Important actions should be in main navigation
408
579
 
409
- 5. **Do not use for non-user content**: ProfileMenu is specifically designed for user account contexts. For general navigation menus, use a regular Dropdown or Menu.
580
+ 3. **Don't use for non-user content**: ProfileMenu is specifically for user accounts
410
581
 
411
- ## Accessibility
582
+ 4. **Don't leave profile empty**: Always provide at least the name
583
+
584
+ ## Performance Considerations
585
+
586
+ ### Lazy Load Menu Content
587
+
588
+ For dynamic menu items, fetch data when needed:
589
+
590
+ ```tsx
591
+ function ProfileMenuWithDynamicItems({ user }) {
592
+ const [menuItems, setMenuItems] = useState(baseMenuItems);
593
+
594
+ const handleOpenChange = async (isOpen) => {
595
+ if (isOpen && !menuItems.includes(dynamicItems)) {
596
+ const items = await fetchUserMenuItems(user.id);
597
+ setMenuItems([...baseMenuItems, ...items]);
598
+ }
599
+ };
600
+
601
+ return (
602
+ <ProfileMenu
603
+ profile={user}
604
+ menuItems={menuItems}
605
+ onOpenChange={handleOpenChange}
606
+ />
607
+ );
608
+ }
609
+ ```
610
+
611
+ ### Memoize Menu Items
612
+
613
+ When menu items are computed, memoize them:
614
+
615
+ ```tsx
616
+ const menuItems = useMemo(() => [
617
+ { label: 'Profile', onClick: handleProfile },
618
+ { label: 'Settings', onClick: handleSettings },
619
+ ...(user.isAdmin ? [{ label: 'Admin', onClick: handleAdmin }] : []),
620
+ { label: 'Sign Out', onClick: handleSignOut },
621
+ ], [user.isAdmin, handleProfile, handleSettings, handleAdmin, handleSignOut]);
622
+ ```
623
+
624
+ ### Optimize Avatar Loading
625
+
626
+ For profile images, ensure proper caching and loading:
627
+
628
+ ```tsx
629
+ <ProfileMenu
630
+ profile={{
631
+ name: user.name,
632
+ image: user.avatarUrl
633
+ ? { src: `${user.avatarUrl}?size=64`, alt: user.name }
634
+ : undefined,
635
+ }}
636
+ />
637
+ ```
412
638
 
413
- - The avatar trigger button has `aria-haspopup` and `aria-expanded` attributes, informing assistive technology that it controls a menu.
414
- - The dropdown menu uses `role="menu"` with `role="menuitem"` for each action, following WAI-ARIA menu button pattern.
415
- - Keyboard navigation is fully supported: **Enter** or **Space** opens the menu, **Arrow Down/Up** navigates items, **Enter** activates a focused item, and **Escape** closes the menu.
416
- - Focus returns to the trigger button when the menu is closed, maintaining a predictable focus flow for keyboard and screen reader users.
639
+ ProfileMenu provides a polished user account interface for admin applications. Place it in your header for easy access to user-related actions and account management.