@cl-light-ds/ui 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/package.json +19 -17
  2. package/src/components/accordion/AccordionTrigger.astro +5 -1
  3. package/src/components/accordion/CHANGELOG.md +9 -0
  4. package/src/components/alert/Alert.astro +42 -3
  5. package/src/components/alert/CHANGELOG.md +19 -0
  6. package/src/components/button/Button.astro +78 -19
  7. package/src/components/button/CHANGELOG.md +22 -0
  8. package/src/components/button-group/ButtonGroup.astro +14 -3
  9. package/src/components/button-group/CHANGELOG.md +17 -0
  10. package/src/components/card/CHANGELOG.md +9 -0
  11. package/src/components/card/Card.astro +22 -0
  12. package/src/components/collapsible/CHANGELOG.md +9 -0
  13. package/src/components/collapsible/CollapsibleTrigger.astro +5 -1
  14. package/src/components/combobox/CHANGELOG.md +27 -0
  15. package/src/components/combobox/Combobox.astro +18 -1
  16. package/src/components/combobox/ComboboxTrigger.astro +32 -2
  17. package/src/components/command-search/CHANGELOG.md +57 -0
  18. package/src/components/command-search/CommandSearch.astro +594 -0
  19. package/src/components/command-search/CommandSearchGroup.astro +43 -0
  20. package/src/components/command-search/CommandSearchItem.astro +64 -0
  21. package/src/components/command-search/classes.ts +18 -0
  22. package/src/components/command-search/index.ts +12 -0
  23. package/src/components/command-search/nothing-matches.svg +42 -0
  24. package/src/components/dialog/CHANGELOG.md +50 -0
  25. package/src/components/dialog/Dialog.astro +14 -3
  26. package/src/components/dialog/DialogClose.astro +28 -12
  27. package/src/components/dialog/DialogContent.astro +19 -1
  28. package/src/components/dialog/DialogTrigger.astro +5 -1
  29. package/src/components/dropdown-menu/CHANGELOG.md +32 -0
  30. package/src/components/dropdown-menu/DropdownMenu.astro +13 -3
  31. package/src/components/dropdown-menu/DropdownMenuRadioGroup.astro +17 -2
  32. package/src/components/dropdown-menu/DropdownMenuTrigger.astro +7 -1
  33. package/src/components/dropdown-menu/dropdown-menu-item-variants.ts +1 -1
  34. package/src/components/empty-state/CHANGELOG.md +18 -0
  35. package/src/components/empty-state/EmptyState.astro +157 -0
  36. package/src/components/empty-state/illustrations/AllCaughtUp.astro +52 -0
  37. package/src/components/empty-state/illustrations/EmptyWorkspaces.astro +56 -0
  38. package/src/components/empty-state/illustrations/LoadError.astro +61 -0
  39. package/src/components/empty-state/illustrations/NoResults.astro +60 -0
  40. package/src/components/empty-state/illustrations/NothingMatches.astro +66 -0
  41. package/src/components/empty-state/illustrations/index.ts +27 -0
  42. package/src/components/empty-state/index.ts +7 -0
  43. package/src/components/favorite-toggle/CHANGELOG.md +13 -0
  44. package/src/components/favorite-toggle/FavoriteToggle.astro +94 -0
  45. package/src/components/favorite-toggle/index.ts +1 -0
  46. package/src/components/field/CHANGELOG.md +18 -0
  47. package/src/components/field/Field.astro +18 -0
  48. package/src/components/field/FieldError.astro +13 -1
  49. package/src/components/field/FieldGroup.astro +12 -3
  50. package/src/components/hover-card/CHANGELOG.md +9 -0
  51. package/src/components/hover-card/HoverCardTrigger.astro +5 -1
  52. package/src/components/input-group/CHANGELOG.md +7 -0
  53. package/src/components/input-group/InputGroup.astro +2 -0
  54. package/src/components/loading-overlay/CHANGELOG.md +25 -0
  55. package/src/components/loading-overlay/LoadingOverlay.astro +179 -0
  56. package/src/components/loading-overlay/index.ts +8 -0
  57. package/src/components/notifications-menu/CHANGELOG.md +29 -0
  58. package/src/components/notifications-menu/NotificationsMenu.astro +375 -0
  59. package/src/components/notifications-menu/NotificationsMenuItem.astro +130 -0
  60. package/src/components/notifications-menu/all-caught-up.svg +28 -0
  61. package/src/components/notifications-menu/index.ts +3 -0
  62. package/src/components/notifications-menu/types.ts +32 -0
  63. package/src/components/option-card/CHANGELOG.md +26 -0
  64. package/src/components/option-card/OptionCard.astro +143 -0
  65. package/src/components/option-card/index.ts +1 -0
  66. package/src/components/organisms/top-bar/CHANGELOG.md +27 -0
  67. package/src/components/organisms/top-bar/TopBar.astro +257 -0
  68. package/src/components/organisms/top-bar/index.ts +2 -0
  69. package/src/components/organisms/top-bar/types.ts +30 -0
  70. package/src/components/organisms/workspace/CHANGELOG.md +80 -0
  71. package/src/components/organisms/workspace/OrganisationOverview.astro +62 -0
  72. package/src/components/organisms/workspace/RecentWorkspaceCard.astro +235 -0
  73. package/src/components/organisms/workspace/RecentWorkspaces.astro +93 -0
  74. package/src/components/organisms/workspace/WorkspaceAvatar.astro +144 -0
  75. package/src/components/organisms/workspace/WorkspaceCard.astro +172 -0
  76. package/src/components/organisms/workspace/WorkspaceGlyph.astro +62 -0
  77. package/src/components/organisms/workspace/WorkspaceIcon.astro +42 -0
  78. package/src/components/organisms/workspace/WorkspaceIconPicker.astro +288 -0
  79. package/src/components/organisms/workspace/WorkspaceIconPickerGlyph.astro +44 -0
  80. package/src/components/organisms/workspace/icons.ts +98 -0
  81. package/src/components/organisms/workspace/index.ts +35 -0
  82. package/src/components/organisms/workspace/labels.ts +54 -0
  83. package/src/components/organisms/workspace/recent-card-rings-strong.png +0 -0
  84. package/src/components/organisms/workspace/types.ts +30 -0
  85. package/src/components/popover/CHANGELOG.md +14 -0
  86. package/src/components/popover/PopoverClose.astro +2 -1
  87. package/src/components/popover/PopoverTrigger.astro +7 -1
  88. package/src/components/profile-menu/CHANGELOG.md +22 -0
  89. package/src/components/profile-menu/ProfileMenu.astro +236 -0
  90. package/src/components/profile-menu/index.ts +2 -0
  91. package/src/components/profile-menu/types.ts +27 -0
  92. package/src/components/search-field/CHANGELOG.md +14 -0
  93. package/src/components/search-field/SearchField.astro +163 -0
  94. package/src/components/search-field/index.ts +1 -0
  95. package/src/components/select/CHANGELOG.md +8 -0
  96. package/src/components/select/SelectTrigger.astro +1 -1
  97. package/src/components/table/CHANGELOG.md +15 -0
  98. package/src/components/table/TableCell.astro +6 -0
  99. package/src/components/table/TableEditableCell.astro +2 -2
  100. package/src/components/table/TableHead.astro +5 -1
  101. package/src/components/table/TablePagination.astro +4 -4
  102. package/src/components/table/TableRow.astro +3 -1
  103. package/src/components/table/table-cell-variants.ts +2 -0
  104. package/src/components/tabs/CHANGELOG.md +16 -0
  105. package/src/components/tabs/Tabs.astro +26 -0
  106. package/src/components/tabs/TabsList.astro +30 -3
  107. package/src/components/toast/CHANGELOG.md +32 -0
  108. package/src/components/toast/Toast.astro +145 -0
  109. package/src/components/toast/Toaster.astro +322 -0
  110. package/src/components/toast/index.ts +9 -0
  111. package/src/components/toggle/CHANGELOG.md +7 -0
  112. package/src/components/toggle-group/CHANGELOG.md +11 -0
  113. package/src/components/toggle-group/ToggleGroup.astro +19 -2
  114. package/src/components/toggle-group/ToggleGroupItem.astro +10 -0
  115. package/src/components/tooltip/CHANGELOG.md +26 -0
  116. package/src/components/tooltip/Tooltip.astro +31 -3
  117. package/src/components/tooltip/TooltipTrigger.astro +5 -1
  118. package/src/lib/command-search.ts +78 -0
  119. package/src/lib/dialog-focus.ts +73 -0
  120. package/src/lib/dropdown-menu-radio-groups.ts +79 -0
  121. package/src/lib/loading-overlay.ts +174 -0
  122. package/src/lib/scroll-lock.ts +97 -0
  123. package/src/lib/toast.ts +127 -0
  124. package/src/lib/toggle-shared.ts +9 -1
  125. package/src/lib/workspace-palette.ts +119 -0
  126. package/src/styles/CHANGELOG.md +35 -0
  127. package/src/styles/globals.css +109 -0
@@ -10,17 +10,30 @@ interface Props extends HTMLAttributes<"button"> {
10
10
  const {
11
11
  class: className = "",
12
12
  size = "default",
13
+ tabindex = 0,
13
14
  ...rest
14
15
  } = Astro.props as Props;
15
16
  ---
16
17
 
18
+ {
19
+ /*
20
+ The "search in popup" field: it shows the committed value and is the control
21
+ people Tab to, so it has the Input's field styling and stays in the Tab order
22
+ (the runtime takes a trigger without a tabindex out of it). The runtime also
23
+ names every trigger "Toggle"; the script below names it by its <label for>
24
+ and its value instead.
25
+ */
26
+ }
17
27
  <button
18
- {...rest}
19
28
  type="button"
29
+ {...rest}
30
+ tabindex={tabindex}
20
31
  data-slot="combobox-trigger"
21
32
  data-size={size}
22
33
  class={cn(
23
- "[&_svg:not([class*='size-'])]:size-4 rounded-lg flex w-full items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=combobox-value]:line-clamp-1 *:data-[slot=combobox-value]:flex *:data-[slot=combobox-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
34
+ "[&_svg:not([class*='size-'])]:size-4 rounded-lg flex w-full items-center justify-between gap-2 whitespace-nowrap text-left outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=combobox-value]:line-clamp-1 *:data-[slot=combobox-value]:flex *:data-[slot=combobox-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
35
+ "border-input bg-card focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 aria-invalid:border-destructive border shadow-xs transition-[color,box-shadow] focus-visible:ring-3 aria-invalid:ring-3",
36
+ "data-[size=sm]:h-8 data-[size=sm]:px-2.5 data-[size=sm]:text-xs data-[size=default]:h-9 data-[size=default]:px-2.5 data-[size=default]:text-sm data-[size=lg]:h-10 data-[size=lg]:px-3.5 data-[size=lg]:text-base",
24
37
  className,
25
38
  )}
26
39
  >
@@ -28,3 +41,20 @@ const {
28
41
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="text-muted-foreground size-4 pointer-events-none"
29
42
  data-slot="combobox-icon"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6 9l6 6l6-6"/></svg>
30
43
  </button>
44
+
45
+ <script>
46
+ // Name each trigger by its label and current value ("Language English"),
47
+ // unless the author already named it with aria-labelledby.
48
+ let uid = 0;
49
+ const ensureId = (el: Element, prefix: string) => (el.id ||= `${prefix}-${++uid}`);
50
+
51
+ for (const trigger of document.querySelectorAll<HTMLButtonElement>("[data-slot='combobox-trigger']")) {
52
+ if (!trigger.id || trigger.hasAttribute("aria-labelledby")) continue;
53
+ const label = document.querySelector(`label[for="${CSS.escape(trigger.id)}"]`);
54
+ if (!label) continue;
55
+ const value = trigger.querySelector("[data-slot='combobox-value']");
56
+ const ids = [ensureId(label, "combobox-label")];
57
+ if (value) ids.push(ensureId(value, "combobox-value"));
58
+ trigger.setAttribute("aria-labelledby", ids.join(" "));
59
+ }
60
+ </script>
@@ -0,0 +1,57 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `CommandSearch` component family (`CommandSearch`, `CommandSearchGroup`, `CommandSearchItem`, and the helpers in `@cl-light-ds/ui/lib/command-search`) are documented in this file.
4
+
5
+ ## Date 15th Oct 2026
6
+ ## Results announcement counts every match
7
+
8
+ - With a per-group `limit`, the screen-reader announcement ("{count} results") counted only the rows shown. It now announces every match: the sum of the group counts (including a remote search's own counts), or a group's matches where it shows no count.
9
+
10
+
11
+ ## Date 15th Oct 2026
12
+ ## Handover gaps: per-group limit (C30, gap G19)
13
+
14
+ ### Added
15
+
16
+ - **`limit`: at most N matches per group** (D67 asks for the first five). Each group shows its first `limit` matches. The count beside the heading still counts every match. Set it on `CommandSearch` for every group, or on one `CommandSearchGroup` (its own wins; `0` means no limit). In `remote` mode it applies to the rendered groups too (`limit` on a result group, or `CommandSearch`'s). There the count stays `count ?? items.length`.
17
+ - The rows past the limit are `hidden` (and marked `data-over-limit`), so ↑ ↓, Home/End, hover and Enter skip them like any non-match. The highlight moves to a shown row if its row is capped.
18
+ - **How it holds:** `@data-slot/command` sets `hidden` on every item each time it filters. It filters again whenever the list's content changes (its own MutationObserver), so a cap applied once would be undone. So the cap is reapplied after every filter pass: an observer on the items' `hidden` attribute runs it again, writing only what differs, so it settles at once. It works out matches with the same filter the runtime uses.
19
+
20
+ ### Fixed
21
+
22
+ - Rows added to the list after a search are now matched by their label when the runtime re-filters. Before, their label hadn't been read yet, so they were matched by `value`.
23
+
24
+ ### Storybook
25
+
26
+ - "Limit: the first 3 matches per group" preview (`limit={3}`, `limit={5}` on Recordings); the remote demo uses `limit={3}`.
27
+
28
+
29
+ ## Handover gaps: triggers don't submit forms (C29, gap G18)
30
+
31
+ ### Fixed
32
+
33
+ - **The trigger button has `type="button"`.** It sits in `DialogTrigger asChild`, whose wrapper can't set a type, so inside a `<form>` opening command search submitted the form.
34
+
35
+
36
+ ## Workspace selection handover (N11)
37
+
38
+ New component, replacing the workspace-selection screen's hand-composed `CommandPalette.astro` and its palette code in `interactions.ts` (gap G8).
39
+
40
+ ### `CommandSearch`
41
+
42
+ - Trigger (D63): a 32px outline `Button` "Search everything…" with a search icon and a `Kbd` showing ⌘K on a Mac, Ctrl K elsewhere. ⌘K / Ctrl K opens the first palette on the page (`shortcut`, default on). `hideTrigger` to open it from your own control (`openCommandSearch()` or `dialog:set`).
43
+ - Palette: the DS `Dialog` (672px, `sm:max-w-2xl`), a large search field (`InputGroup` size lg) with a secondary Search button, results, and a footer with ↑ ↓ / ↵ / esc hints (replaceable via the `footer` slot).
44
+ - Searching (D116, D122, D142): nothing is listed until a search runs; a hint says how. Enter or Search runs it; typing alone changes nothing, and emptying the field goes back to the hint. While it runs: a spinner and "Searching everything…". Enter again chooses the highlighted item.
45
+ - Results grouped (`CommandSearchGroup`, heading in small caps with the number of matches beside it, D67); rows (`CommandSearchItem`) with optional `media` and `meta` slots, highlighted while active. Choosing fires `command-search:select` (cancelable), closes the palette, and follows `href` if given.
46
+ - "Nothing matches" (D187): the 184×124 illustration (`nothing-matches.svg`), a title and a line of text.
47
+ - Two modes: `filter` (default) filters the items you put in, by label and keywords, case-insensitive substring, keeping your order; `delay` shows the loading state first. `remote` fires `command-search:search` with the query and waits for `setCommandSearchResults(root, groups, { query })` (stale answers are ignored), rendering the groups itself, or keeping rows you added.
48
+ - A11y: the runtime makes the field a combobox over a listbox (`aria-activedescendant`, options, groups labelled by their heading); a polite live region announces "Searching everything…", the number of results or "Nothing matches".
49
+
50
+ ### Built on `@data-slot/command`
51
+
52
+ - Used: item and group registration, `role`s, active item, arrow / Home / End / Alt+arrow navigation, Enter and click selection, hover highlight, hiding groups with no matches, the empty element, `setSearch` / `select`.
53
+ - Added on top: search on Enter or the button instead of as you type (the field's `input` event is stopped before the runtime sees it), the idle hint and loading states, a substring filter that keeps the given order, match counts, the remote mode and its result rendering, `href` navigation and closing on select, the platform shortcut label and the global shortcut. The runtime's Ctrl+J/K/N/P bindings are off (Ctrl K opens the palette).
54
+
55
+ ### Storybook
56
+
57
+ - "Command Search" section: filter mode with workspaces, recordings and assets; remote mode with a simulated server.