@ceed/ads 1.23.3 → 1.23.4

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 (43) hide show
  1. package/dist/components/data-display/Badge.md +71 -39
  2. package/dist/components/data-display/InfoSign.md +74 -98
  3. package/dist/components/data-display/Typography.md +310 -61
  4. package/dist/components/feedback/CircularProgress.md +257 -0
  5. package/dist/components/feedback/Skeleton.md +280 -0
  6. package/dist/components/feedback/llms.txt +2 -0
  7. package/dist/components/inputs/ButtonGroup.md +115 -106
  8. package/dist/components/inputs/Calendar.md +98 -459
  9. package/dist/components/inputs/CurrencyInput.md +181 -8
  10. package/dist/components/inputs/DatePicker.md +108 -436
  11. package/dist/components/inputs/DateRangePicker.md +130 -496
  12. package/dist/components/inputs/FilterMenu.md +169 -19
  13. package/dist/components/inputs/FilterableCheckboxGroup.md +119 -24
  14. package/dist/components/inputs/FormControl.md +368 -0
  15. package/dist/components/inputs/IconButton.md +137 -88
  16. package/dist/components/inputs/MonthPicker.md +95 -427
  17. package/dist/components/inputs/MonthRangePicker.md +89 -471
  18. package/dist/components/inputs/PercentageInput.md +183 -19
  19. package/dist/components/inputs/RadioButton.md +163 -35
  20. package/dist/components/inputs/RadioList.md +241 -0
  21. package/dist/components/inputs/RadioTileGroup.md +146 -62
  22. package/dist/components/inputs/Select.md +219 -328
  23. package/dist/components/inputs/Slider.md +334 -0
  24. package/dist/components/inputs/Switch.md +136 -376
  25. package/dist/components/inputs/Textarea.md +209 -11
  26. package/dist/components/inputs/Uploader/Uploader.md +145 -66
  27. package/dist/components/inputs/llms.txt +3 -0
  28. package/dist/components/navigation/Breadcrumbs.md +80 -322
  29. package/dist/components/navigation/Dropdown.md +92 -221
  30. package/dist/components/navigation/IconMenuButton.md +40 -502
  31. package/dist/components/navigation/InsetDrawer.md +68 -738
  32. package/dist/components/navigation/Link.md +39 -298
  33. package/dist/components/navigation/Menu.md +92 -285
  34. package/dist/components/navigation/MenuButton.md +55 -448
  35. package/dist/components/navigation/Pagination.md +47 -338
  36. package/dist/components/navigation/ProfileMenu.md +45 -268
  37. package/dist/components/navigation/Stepper.md +160 -28
  38. package/dist/components/navigation/Tabs.md +57 -316
  39. package/dist/components/surfaces/Sheet.md +150 -333
  40. package/dist/guides/ThemeProvider.md +116 -0
  41. package/dist/guides/llms.txt +9 -0
  42. package/dist/llms.txt +8 -0
  43. package/package.json +1 -1
@@ -2,7 +2,9 @@
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 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.
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.
6
8
 
7
9
  ```tsx
8
10
  <ProfileMenu
@@ -52,11 +54,11 @@ function Header() {
52
54
  }
53
55
  ```
54
56
 
55
- ## Examples
57
+ ## Profile Variations
56
58
 
57
59
  ### Default
58
60
 
59
- ProfileMenu with full profile information including name, chip, and caption.
61
+ ProfileMenu with full profile information including name, chip badge, and caption.
60
62
 
61
63
  ```tsx
62
64
  <ProfileMenu
@@ -81,7 +83,7 @@ ProfileMenu with full profile information including name, chip, and caption.
81
83
 
82
84
  ### Without Caption
83
85
 
84
- Profile showing only the name and chip badge.
86
+ Profile showing only the name and chip badge, without a secondary caption line.
85
87
 
86
88
  ```tsx
87
89
  <ProfileMenu
@@ -105,7 +107,7 @@ Profile showing only the name and chip badge.
105
107
 
106
108
  ### Without Chip
107
109
 
108
- Profile showing name and caption without a badge.
110
+ Profile showing the name and caption, without a badge chip.
109
111
 
110
112
  ```tsx
111
113
  <ProfileMenu
@@ -129,7 +131,7 @@ Profile showing name and caption without a badge.
129
131
 
130
132
  ### Only Name
131
133
 
132
- Minimal profile with just the user's name.
134
+ Minimal profile display with just the user's name. Useful for compact layouts where additional context is not needed.
133
135
 
134
136
  ```tsx
135
137
  <ProfileMenu
@@ -152,7 +154,7 @@ Minimal profile with just the user's name.
152
154
 
153
155
  ### Without Menu Items
154
156
 
155
- Profile card without any menu actions.
157
+ Profile card without any action menu items. The dropdown displays only the user information.
156
158
 
157
159
  ```tsx
158
160
  <ProfileMenu
@@ -166,9 +168,9 @@ Profile card without any menu actions.
166
168
  />
167
169
  ```
168
170
 
169
- ### Sizes
171
+ ## Sizes
170
172
 
171
- ProfileMenu supports different sizes for various layouts.
173
+ ProfileMenu supports `md` (default) and `sm` size variants for use in different layout densities.
172
174
 
173
175
  ```tsx
174
176
  <Stack direction="row" gap="150px">
@@ -203,9 +205,11 @@ ProfileMenu supports different sizes for various layouts.
203
205
  </Stack>
204
206
  ```
205
207
 
208
+ ## Avatar
209
+
206
210
  ### With Profile Image
207
211
 
208
- Display a custom avatar image instead of generated initials.
212
+ When a user has a profile picture, pass the `image` property with `src` and `alt`. The image replaces the auto-generated initials.
209
213
 
210
214
  ```tsx
211
215
  <ProfileMenu
@@ -233,7 +237,7 @@ Display a custom avatar image instead of generated initials.
233
237
 
234
238
  ### With Korean Name
235
239
 
236
- ProfileMenu automatically generates initials from various name formats.
240
+ ProfileMenu automatically generates initials from various name formats, including Korean names.
237
241
 
238
242
  ```tsx
239
243
  <>
@@ -250,9 +254,11 @@ ProfileMenu automatically generates initials from various name formats.
250
254
  </>
251
255
  ```
252
256
 
257
+ ## Controlled vs Uncontrolled
258
+
253
259
  ### Controlled
254
260
 
255
- Programmatically control the menu's open state.
261
+ Use the `open` and `onOpenChange` props to control the menu's open state programmatically.
256
262
 
257
263
  ```tsx
258
264
  <ProfileMenu {...args} open={open} onOpenChange={setOpen} />
@@ -260,7 +266,7 @@ Programmatically control the menu's open state.
260
266
 
261
267
  ### Uncontrolled
262
268
 
263
- Let the component manage its own open state internally.
269
+ Use `defaultOpen` to set the initial state, then let the component manage its own open/close behavior internally.
264
270
 
265
271
  ```tsx
266
272
  <ProfileMenu
@@ -283,24 +289,6 @@ Let the component manage its own open state internally.
283
289
  />
284
290
  ```
285
291
 
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
-
304
292
  ## Common Use Cases
305
293
 
306
294
  ### Header Navigation
@@ -310,7 +298,7 @@ function AppHeader() {
310
298
  const { user, signOut } = useAuth();
311
299
 
312
300
  return (
313
- <header>
301
+ <header style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
314
302
  <Logo />
315
303
  <Navigation />
316
304
  <ProfileMenu
@@ -323,7 +311,6 @@ function AppHeader() {
323
311
  menuItems={[
324
312
  { label: 'My Profile', onClick: () => navigate('/profile') },
325
313
  { label: 'Account Settings', onClick: () => navigate('/settings') },
326
- { label: 'Help & Support', onClick: () => window.open('/help') },
327
314
  { label: 'Sign Out', onClick: signOut },
328
315
  ]}
329
316
  />
@@ -335,25 +322,18 @@ function AppHeader() {
335
322
  ### Multi-Role User
336
323
 
337
324
  ```tsx
338
- function RoleBasedProfileMenu({ user, currentRole, switchRole }) {
325
+ function RoleBasedProfileMenu({ user, currentRole, switchRole, signOut }) {
339
326
  const menuItems = [
340
327
  { label: 'My Profile', onClick: () => navigate('/profile') },
341
328
  { label: 'Settings', onClick: () => navigate('/settings') },
342
- ];
343
-
344
- // Add role switching if user has multiple roles
345
- if (user.roles.length > 1) {
346
- user.roles
329
+ ...user.roles
347
330
  .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() });
331
+ .map((role) => ({
332
+ label: `Switch to ${role}`,
333
+ onClick: () => switchRole(role),
334
+ })),
335
+ { label: 'Sign Out', onClick: signOut },
336
+ ];
357
337
 
358
338
  return (
359
339
  <ProfileMenu
@@ -391,249 +371,46 @@ function OrgProfileMenu({ user, organization }) {
391
371
  }
392
372
  ```
393
373
 
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
-
523
374
  ## Best Practices
524
375
 
525
- ### Do
526
-
527
- 1. **Include essential actions**: Always include profile and sign-out options
376
+ 1. **Always include essential actions**: At minimum, provide access to profile viewing and sign-out.
528
377
 
529
378
  ```tsx
530
- // ✅ Good: Essential menu items
379
+ // ✅ Good: Essential menu items present
531
380
  <ProfileMenu
532
381
  menuItems={[
533
382
  { label: 'Profile', onClick: handleProfile },
534
- { label: 'Settings', onClick: handleSettings },
535
383
  { label: 'Sign Out', onClick: handleSignOut },
536
384
  ]}
537
385
  />
538
- ```
539
386
 
540
- 2. **Show user context**: Display role or organization context in the chip
541
-
542
- ```tsx
543
- // ✅ Good: Clear user context
544
- <ProfileMenu
545
- profile={{
546
- name: 'Jane Smith',
547
- caption: 'jane@company.com',
548
- chip: 'Admin', // Shows current role
549
- }}
550
- />
387
+ // Bad: Missing sign-out option
388
+ <ProfileMenu menuItems={[{ label: 'Profile', onClick: handleProfile }]} />
551
389
  ```
552
390
 
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
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.
560
392
 
561
393
  ```tsx
562
- // Bad: Too many items
394
+ // Good: Clear user context
563
395
  <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
- ]}
396
+ profile={{ name: 'Jane Smith', caption: 'jane@company.com', chip: 'Admin' }}
575
397
  />
576
398
  ```
577
399
 
578
- 2. **Don't hide critical actions**: Important actions should be in main navigation
579
-
580
- 3. **Don't use for non-user content**: ProfileMenu is specifically for user accounts
581
-
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:
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.
589
401
 
590
402
  ```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]);
403
+ // Bad: Too many items in the dropdown
404
+ <ProfileMenu menuItems={[item1, item2, item3, item4, item5, item6, item7, item8, item9]} />
622
405
  ```
623
406
 
624
- ### Optimize Avatar Loading
407
+ 4. **Provide avatar images when available**: Real profile photos help users quickly identify the active account, especially in multi-user or shared environments.
625
408
 
626
- For profile images, ensure proper caching and loading:
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.
627
410
 
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
- ```
411
+ ## Accessibility
638
412
 
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.
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.