@cueplusplus/ui 0.17.0 → 0.18.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 (204) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/dist/chrome/empty-state.js +8 -4
  3. package/dist/chrome/navigation-menu.js +3 -2
  4. package/dist/chrome/panel.js +2 -1
  5. package/dist/chrome/row.js +4 -3
  6. package/dist/chrome/scroll-area.js +4 -3
  7. package/dist/chrome/segmented-control.js +2 -1
  8. package/dist/chrome/tabs.js +5 -2
  9. package/dist/chrome/toolbar.js +5 -3
  10. package/dist/color/color-field.d.ts +7 -0
  11. package/dist/date/_trigger.js +4 -1
  12. package/dist/date/calendar.js +15 -9
  13. package/dist/forms/_chassis.d.ts +10 -2
  14. package/dist/forms/_chassis.js +15 -5
  15. package/dist/forms/_listbox.js +18 -13
  16. package/dist/forms/checkbox.js +9 -6
  17. package/dist/forms/field.js +5 -5
  18. package/dist/forms/input-group.js +11 -2
  19. package/dist/forms/multi-select.js +4 -3
  20. package/dist/forms/number-field.js +6 -3
  21. package/dist/forms/otp-field.js +15 -6
  22. package/dist/forms/radio-group.js +7 -5
  23. package/dist/forms/select.js +8 -5
  24. package/dist/forms/slider.js +5 -3
  25. package/dist/forms/switch.js +6 -4
  26. package/dist/forms/tags-input.js +4 -3
  27. package/dist/forms/textarea.js +2 -1
  28. package/dist/forms/toggle-group.js +2 -1
  29. package/dist/forms/toggle.js +3 -1
  30. package/dist/instruments/meter.js +2 -1
  31. package/dist/instruments/progress.js +6 -3
  32. package/dist/instruments/stat.js +5 -3
  33. package/dist/instruments/table.js +3 -2
  34. package/dist/layout/_collapse.js +24 -8
  35. package/dist/layout/accordion.js +2 -1
  36. package/dist/layout/breadcrumb.js +8 -7
  37. package/dist/layout/card.js +2 -1
  38. package/dist/layout/collapsible.js +2 -1
  39. package/dist/layout/link.d.ts +14 -0
  40. package/dist/layout/link.js +4 -4
  41. package/dist/layout/pagination.js +7 -8
  42. package/dist/overlays/_surface.d.ts +4 -4
  43. package/dist/overlays/_surface.js +8 -7
  44. package/dist/overlays/alert-dialog.js +1 -1
  45. package/dist/overlays/command-palette.js +23 -8
  46. package/dist/overlays/dialog.js +1 -1
  47. package/dist/overlays/drawer.js +8 -1
  48. package/dist/overlays/hover-card.js +3 -1
  49. package/dist/overlays/popover.js +2 -1
  50. package/dist/overlays/toast.js +8 -4
  51. package/dist/overlays/tooltip.js +3 -4
  52. package/dist/primitives/avatar.js +6 -2
  53. package/dist/primitives/button.d.ts +1 -1
  54. package/dist/primitives/button.js +10 -7
  55. package/dist/primitives/chip.d.ts +1 -37
  56. package/dist/primitives/chip.js +14 -46
  57. package/dist/primitives/icon-button.d.ts +1 -1
  58. package/dist/primitives/kbd.js +2 -2
  59. package/dist/primitives/skeleton.js +2 -1
  60. package/dist/system/_style-accordion-rule.js +32 -0
  61. package/dist/system/_style-avatar.js +20 -0
  62. package/dist/system/_style-body-leading.js +1 -3
  63. package/dist/system/_style-body.js +7 -2
  64. package/dist/system/_style-caption-ink.js +17 -0
  65. package/dist/system/_style-caption-size.js +19 -0
  66. package/dist/system/_style-caption-weight.js +18 -0
  67. package/dist/system/_style-card-gap.js +14 -0
  68. package/dist/system/_style-cell.js +18 -0
  69. package/dist/system/_style-check-glyph.js +14 -0
  70. package/dist/system/_style-check.js +8 -1
  71. package/dist/system/_style-chip.js +41 -1
  72. package/dist/system/_style-choice-gap.js +15 -0
  73. package/dist/system/_style-collapse.js +81 -1
  74. package/dist/system/_style-control-gap.js +14 -0
  75. package/dist/system/_style-control-label.js +8 -1
  76. package/dist/system/_style-crumb.js +44 -0
  77. package/dist/system/_style-day.js +25 -0
  78. package/dist/system/_style-disabled.js +70 -0
  79. package/dist/system/_style-disclosure.js +21 -0
  80. package/dist/system/_style-empty-state.js +42 -0
  81. package/dist/system/_style-field-chassis.js +38 -0
  82. package/dist/system/_style-field-gap.js +12 -0
  83. package/dist/system/_style-glyph-ink.js +20 -0
  84. package/dist/system/_style-glyph-opacity.js +20 -0
  85. package/dist/system/_style-glyph-size.js +21 -0
  86. package/dist/system/_style-group-gap.js +15 -0
  87. package/dist/system/_style-group-label-pad.js +14 -0
  88. package/dist/system/_style-group-label.js +24 -0
  89. package/dist/system/_style-help.js +10 -1
  90. package/dist/system/_style-hover-card-width.js +15 -0
  91. package/dist/system/_style-kbd.js +13 -1
  92. package/dist/system/_style-link.js +15 -3
  93. package/dist/system/_style-menu.js +14 -1
  94. package/dist/system/_style-meter.js +15 -0
  95. package/dist/system/_style-nav-menu.js +48 -0
  96. package/dist/system/_style-option.js +61 -4
  97. package/dist/system/_style-otp.js +15 -0
  98. package/dist/system/_style-outline-hover.js +18 -0
  99. package/dist/system/_style-page.js +17 -0
  100. package/dist/system/_style-palette.js +18 -0
  101. package/dist/system/_style-panel.js +21 -0
  102. package/dist/system/_style-popover-width.js +15 -0
  103. package/dist/system/_style-radio.js +19 -0
  104. package/dist/system/_style-row-disabled.js +17 -0
  105. package/dist/system/_style-row.js +30 -0
  106. package/dist/system/_style-scrollbar.js +19 -0
  107. package/dist/system/_style-segment-pad.js +15 -0
  108. package/dist/system/_style-skeleton.js +15 -0
  109. package/dist/system/_style-slider.js +26 -0
  110. package/dist/system/_style-stat.js +31 -0
  111. package/dist/system/_style-stepper.js +16 -0
  112. package/dist/system/_style-switch.js +26 -0
  113. package/dist/system/_style-tab-hover.js +15 -0
  114. package/dist/system/_style-text-focus.js +26 -0
  115. package/dist/system/_style-toast.js +22 -0
  116. package/dist/system/_style-toggle.js +50 -0
  117. package/dist/system/_style-toolbar.js +23 -0
  118. package/dist/system/_style-tooltip.js +30 -1
  119. package/manifest/components/accordion.json +22 -1
  120. package/manifest/components/alert-dialog.json +7 -0
  121. package/manifest/components/app-bar.json +42 -0
  122. package/manifest/components/autocomplete.json +48 -1
  123. package/manifest/components/avatar-group.json +7 -0
  124. package/manifest/components/avatar.json +7 -0
  125. package/manifest/components/breadcrumb.json +7 -2
  126. package/manifest/components/button.json +16 -1
  127. package/manifest/components/calendar.json +6 -0
  128. package/manifest/components/card.json +1 -0
  129. package/manifest/components/channel-matrix.json +6 -0
  130. package/manifest/components/chart-tooltip-content.json +6 -0
  131. package/manifest/components/checkbox-group.json +22 -1
  132. package/manifest/components/checkbox.json +22 -1
  133. package/manifest/components/chip.json +6 -0
  134. package/manifest/components/collapsible.json +22 -0
  135. package/manifest/components/color-field.json +29 -0
  136. package/manifest/components/color-picker.json +19 -0
  137. package/manifest/components/combobox.json +48 -1
  138. package/manifest/components/command-palette.json +11 -0
  139. package/manifest/components/composer.json +19 -0
  140. package/manifest/components/context-menu.json +6 -0
  141. package/manifest/components/date-field.json +18 -0
  142. package/manifest/components/date-picker.json +22 -0
  143. package/manifest/components/date-range-picker.json +22 -0
  144. package/manifest/components/dialog.json +7 -0
  145. package/manifest/components/disclosure.json +22 -0
  146. package/manifest/components/dmx-bar.json +6 -0
  147. package/manifest/components/dmx-strip.json +6 -0
  148. package/manifest/components/drawer.json +7 -0
  149. package/manifest/components/dropdown-menu.json +6 -0
  150. package/manifest/components/empty-state.json +13 -0
  151. package/manifest/components/env-var-input.json +19 -0
  152. package/manifest/components/field-description.json +2 -1
  153. package/manifest/components/field-error.json +2 -1
  154. package/manifest/components/field-label.json +2 -1
  155. package/manifest/components/field.json +2 -1
  156. package/manifest/components/hover-card.json +8 -0
  157. package/manifest/components/input-group.json +21 -0
  158. package/manifest/components/input.json +19 -0
  159. package/manifest/components/kbd.json +2 -0
  160. package/manifest/components/link.json +23 -0
  161. package/manifest/components/menubar.json +6 -0
  162. package/manifest/components/meter.json +1 -0
  163. package/manifest/components/multi-select.json +49 -1
  164. package/manifest/components/musical-time-input.json +19 -0
  165. package/manifest/components/navigation-menu.json +16 -0
  166. package/manifest/components/number-field.json +21 -0
  167. package/manifest/components/otp-field.json +20 -0
  168. package/manifest/components/pagination.json +19 -0
  169. package/manifest/components/panel-header.json +3 -0
  170. package/manifest/components/panel.json +3 -0
  171. package/manifest/components/password-input.json +19 -0
  172. package/manifest/components/popover.json +7 -0
  173. package/manifest/components/progress.json +4 -0
  174. package/manifest/components/radio-group.json +6 -0
  175. package/manifest/components/radio.json +6 -0
  176. package/manifest/components/row.json +3 -0
  177. package/manifest/components/scroll-area.json +3 -1
  178. package/manifest/components/scrollable-tabs-list.json +3 -0
  179. package/manifest/components/scrub-input.json +19 -0
  180. package/manifest/components/seam-list.json +3 -0
  181. package/manifest/components/search-input.json +19 -0
  182. package/manifest/components/segmented-control.json +1 -0
  183. package/manifest/components/select.json +25 -0
  184. package/manifest/components/sheet.json +6 -0
  185. package/manifest/components/skeleton.json +2 -0
  186. package/manifest/components/slider.json +8 -0
  187. package/manifest/components/stat.json +8 -0
  188. package/manifest/components/switch.json +22 -0
  189. package/manifest/components/table-scroll-region.json +2 -0
  190. package/manifest/components/table.json +2 -0
  191. package/manifest/components/tabs.json +3 -0
  192. package/manifest/components/tags-input.json +49 -1
  193. package/manifest/components/textarea.json +19 -0
  194. package/manifest/components/theme-configurator.json +6 -0
  195. package/manifest/components/time-field.json +18 -0
  196. package/manifest/components/toast.json +9 -0
  197. package/manifest/components/toggle-group.json +2 -1
  198. package/manifest/components/toggle.json +28 -0
  199. package/manifest/components/toolbar.json +19 -0
  200. package/manifest/components/tooltip.json +11 -0
  201. package/manifest/fixtures.json +45 -0
  202. package/manifest/manifest.json +84 -84
  203. package/manifest/tokens.json +155 -1
  204. package/package.json +5 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,89 @@
1
1
  # @cueplusplus/ui
2
2
 
3
+ ## 0.18.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 59deac9: `ColorField` documents `aria-label`. The field draws no visible label, so it needs a name from `aria-label` or from `aria-labelledby` pointing at a label of your own — without either the input has none. The prop was always accepted (it comes from React Aria); it is now in the component's documentation and manifest, so whoever builds one — a person or an agent reading the manifest — is told.
8
+ - 2dd4248: The manifest's fixture catalogue (`manifest/fixtures.json`) names six more values a tool can place in a prop: `children.toggles`, three toggles for a `ToggleGroup`; `layout.show-crumbs-long` and `layout.patch-steps-long`, breadcrumbs and steps with long words; and `agent.permission-scopes`, `agent.permission-rules` and `agent.permission-dirs`, the scopes, command rule and directory a `PermissionScopes` grant is written with. No component changes.
9
+ - @cueplusplus/tokens@0.18.1
10
+
11
+ ## 0.18.0
12
+
13
+ ### Minor Changes
14
+
15
+ - d1eef08: The style contract gains four optional names for the parts of agent-native.com's own components that no earlier round measured (looks-fidelity round 6, spec §11, Graphite's lane R6.G). Each is `initial` on the shared `[data-style]` reset, `console` declines it, and each reader falls back to exactly what its component drew, so under no set and under every set that does not name it nothing moves.
16
+
17
+ - `--cue-style-kbd-fill`: a `Kbd`'s fill, falling back to the `surface-2` it drew.
18
+ - `--cue-style-option-highlight-ink`: a highlighted option row's ink, falling back to `fg`.
19
+ - `--cue-style-secondary-hover-ground`: the secondary `Button`'s ground under the pointer, falling back to its resting ground, which it kept before.
20
+ - `--cue-style-option-selected-hover-ground`: a selected listbox row's ground under the pointer, falling back to the ground it paints selected and highlighted. A list opens with its selected row highlighted, so a set that grounds that row needs this for the pointer to paint its hover over it.
21
+
22
+ The `graphite` set declares the four, and eleven names earlier rounds added that it had left alone, each measured from agent-native.com: a 20px key on `surface-3`, 40.75px option rows with 4px list padding, half-radius menu rows, the highlighted and selected inks, the selected row on the raised `surface-1` (`surface-3` under the pointer), the secondary tone's hover edge, and table cells that clamp their padding from 12px at a phone to 16px at a desktop.
23
+
24
+ - d1eef08: The style contract gains thirteen optional names for the parts of replit.com's own components that no earlier round measured (looks-fidelity round 6, spec §11, Kiln's lane R6.K). Each is `initial` on the shared `[data-style]` reset, `console` declines it, and each reader falls back to exactly what its component drew, so under no set and under every set that does not name it nothing moves. The `kiln` set declares them.
25
+
26
+ - **Disclosures** (`Accordion`, `Collapsible`, `Disclosure`): `--cue-style-collapse-size`, `-collapse-leading`, `-collapse-hover-ground`, `-collapse-radius`, `-collapse-body-ink`, and `-accordion-rule-ink` for the rule between sections.
27
+ - **Toggles**: `--cue-style-toggle-pressed-ink` and `-toggle-hover-ground`.
28
+ - **Options and lists** (`Select`, `Combobox`, `Autocomplete`, `MultiSelect`): `--cue-style-option-selected-ground` and `-listbox-pad`. A selected row under the pointer, or the one a select opens on, keeps the highlight ground unless a set names a selected ground.
29
+ - **Chip, NavigationMenu, Dialog**: `--cue-style-chip-ink`, `-nav-caret-ink`, `-dialog-pad`.
30
+
31
+ The docs' `Link` tile now draws a link: `LinkProps` declares its `href` and `children`, which it took from the anchor's attributes without naming them, so the props table and a propSet could not.
32
+
33
+ - d1eef08: The style contract gains seventy-two optional names for the parts of coss.com/ui's own components that no earlier round measured (looks-fidelity round 6, spec §11: the coverage closure, Porcelain's lane R6.P, rows P140–P193). Each is `initial` on the shared `[data-style]` reset and `console` declines it. Each reader falls back to exactly what its component drew before, so under no set, and under every set that does not name it, nothing moves. The `porcelain` set declares all seventy-two.
34
+
35
+ - **Groups and choices**: `--cue-style-group-gap` (`ToggleGroup`, the `Tabs` list) and `-choice-gap` (`CheckboxGroup`, `RadioGroup`).
36
+ - **Captions and glyphs**: `--cue-style-caption-size`, `-caption-weight`, `-caption-ink` (an avatar's initials, a readout, a calendar's caption); `-glyph-ink`, `-glyph-size` and `-glyph-opacity` for a control's glyphs — the opacity only on the affordance ones: a select's and a filterable field's chevron, the date trigger's mark, a calendar's month arrows and an `InputGroup` gutter's glyphs.
37
+ - **Buttons and breadcrumbs**: `--cue-style-control-gap`, `-outline-hover-ground`, `-outline-hover-edge`, `-crumb-separator-opacity`.
38
+ - **Disclosures and cards**: `--cue-style-collapse-caret-opacity`, `-card-gap`, `-check-glyph-size`.
39
+ - **Menus and the palette**: `--cue-style-group-label-size`, `-group-label-ink`, `-group-label-pad`, `-row-disabled-opacity`, `-menu-min-width`, `-menu-separator-inset`, `-palette-rule`, `-palette-footer-pad`.
40
+ - **EmptyState**: `--cue-style-empty-title-face`, `-empty-title-size`, `-empty-title-weight`, `-empty-title-leading`, `-empty-icon-size`, `-empty-gap`, `-empty-pad`.
41
+ - **Panel, Kbd, Skeleton, ScrollArea, Meter**: `--cue-style-panel-pad-y`, `-panel-pad-x`, `-panel-rule`, `-kbd-leading`, `-skeleton-radius`, `-scrollbar-size`, `-scrollbar-thumb`, `-meter-radius`.
42
+ - **Slider, NumberField, OTPField, Pagination**: `--cue-style-slider-track-height` (the track falls back to `0.125rem`, which is half of Tailwind's default spacing step; a consumer who changed `--spacing` drew half of theirs, and draws 2px now), `-slider-track-ink`, `-slider-thumb-size`, `-slider-thumb-fill`, `-slider-thumb-rim`, `-slider-thumb-edge`, `-stepper-width`, `-otp-gap`, `-page-current-ground`, `-page-current-rim`, `-page-current-edge`.
43
+ - **Switch, Radio, Table, Toast**: `--cue-style-switch-edge`, `-radio-checked-ground`, `-radio-dot-ink`, `-radio-dot-size`, `-cell-pad`, `-cell-leading`, `-toast-pad-y`, `-toast-pad-x`, `-toast-width`.
44
+ - **Toolbar**: `--cue-style-toolbar-rim`, `-toolbar-edge`, `-toolbar-radius`, `-toolbar-pad`, `-toolbar-height`, `-toolbar-gap`, `-toolbar-separator-height`.
45
+ - **Chip, Calendar, Tabs, SegmentedControl, Popover, HoverCard**: `--cue-style-chip-gap`, `-day-size` (the days, the weekday heads, the month-nav buttons and the caption row), `-day-ink`, `-segment-pad`, `-tab-hover-ink`, `-popover-width`, `-hover-card-width`.
46
+
47
+ Three fixes reach every Look. `MultiSelect` and `TagsInput` set their typing input one line tall, so an `md` field is 32px beside a 32px `Input` rather than 38px, chips or none; a second row of chips still grows it. `OTPField`'s slots are square, one control rung wide, as its documentation always said: the `w-auto` beside the size class won the cascade, and every slot drew as wide as an empty input. An `InputGroup`'s gutters read `--cue-style-glyph-ink`, falling back to the `fg-subtle` they drew.
48
+
49
+ The `glaze` pack's stroke pairs (`stroke-from`, `stroke-to`, `stroke-overlay-from`, `stroke-overlay-to`) are opaque mixes now, measured from coss.com/ui's field and popup edges, which composite over their own grounds where the translucent border roles drew a step darker over a sunken stage in dark mode.
50
+
51
+ - d1eef08: The style contract gains forty-six optional names for the parts of a source's own components that no earlier round measured (looks-fidelity round 6, spec §11: the coverage closure, Tender's lane R6.T, rows T123–T157). Each is `initial` on the shared `[data-style]` reset and `console` declines it. Each reader falls back to exactly what its component drew before, so under no set, and under every set that does not name it, nothing moves.
52
+
53
+ - **Disclosures** (`Accordion`, `Collapsible`, `Disclosure`): `--cue-style-accordion-rule-style` (the rule between sections, `solid` or `dashed`, through Tailwind's `--tw-border-style` slot as the footer's rules are), `-collapse-pad`, `-collapse-gap`, `-collapse-hover-ink`, `-collapse-open-ink` and `-collapse-body-pad`.
54
+ - **Fields**: `--cue-style-field-pad` and `-field-gap` (multipliers), `-field-hover-edge`, `-help-leading`, and `-text-focus-offset` for a text control's, a link's and a disclosure trigger's focus ring. (A `-invalid-edge` came and went in the same release: Tender refuses stripe's pale-red invalid edge, so no set spent it.) The hover edge never paints over a focused field's edge: a grouped field's rim (`controlGroupFocusClasses`) now reads `has-focus:` rather than `focus-within:`, which Tailwind emits after the hover edge, so a focused `InputGroup`, `Combobox`, `MultiSelect`, `TagsInput` or `Autocomplete` keeps its `border-strong` rim under the pointer, and an invalid one keeps `danger`.
55
+ - **Options** (`Select`, `Combobox`, `Autocomplete`, `MultiSelect`): `--cue-style-option-pad`, `-option-leading`, `-option-height`.
56
+ - **Checkbox, Switch, Radio**: `--cue-style-control-label-leading`, `-check-hover-edge`, `-switch-thumb`, `-switch-disabled-thumb`.
57
+ - **Disabled controls**: `--cue-style-disabled-opacity` (replacing the fixed 40% fade), `-disabled-fill`, `-disabled-ink`, and `-disabled-edge` (the rim the two transparent button tones draw when disabled; they keep their ground).
58
+ - **Toggle** (and `ToggleGroup`'s items): `--cue-style-toggle-edge`, `-toggle-ink`, `-toggle-hover-ink`, `-toggle-hover-edge`, `-toggle-pressed-ground`, `-toggle-pressed-edge`.
59
+ - **Stat**: `--cue-style-stat-size` and `-stat-detail-size` (scaled with the type), `-stat-weight`, `-stat-leading`, `-stat-tracking`, `-stat-detail-leading`, `-stat-gap`.
60
+ - **Row**, in the rule idiom: `--cue-style-row-rule-style`, `-row-ink`, `-row-block-pad`.
61
+ - **Chip**: `--cue-style-chip-leading`, and the tag volume's `-tag-pad` and `-tag-edge`.
62
+ - **Tooltip**: `--cue-style-tooltip-tracking` and `-tooltip-radius` (stripe.com's overlays take three corners: its dialog, its popover and its tooltip).
63
+ - **Links and navigation**: `--cue-style-link-hover-ink` (apart from the header nav's hover), `-nav-height` and `-nav-open-ground` for `NavigationMenu`'s trigger. The trigger's height is an arbitrary value now, which `tailwind-merge` knows is a height, so a `className` height on a trigger (`h-auto`) takes effect where the control height used to win over it.
64
+
65
+ The Tender style set declares them, measured off stripe.com's own design system (the hds components its homepage loads, injected where it does not render them), alongside the existing names it now also declares: `-collapse-height`, `-tooltip-pad`, `-input-leading`, `-textarea-pad`, `-chip-height`, `-chip-size`, `-link-weight`, `-secondary-hover-ink`, `-secondary-hover-edge`, `-nav-ink`, `-nav-pad` and `-hover-ink`.
66
+
67
+ Two behaviours a consumer can see without any style set. A disabled `Button` paints its tone's disabled fill, ink and edge (`--cue-style-disabled-fill`, `-disabled-ink`, `-disabled-edge`), each falling back to the tone's own resting colour, so a `Button` draws what it drew — but a `className` that recolours a `Button` (`bg-danger`) no longer reaches it while it is disabled, where the tone's own colour does: recolour the disabled state too (`disabled:bg-danger`). And the `NavigationMenu` trigger's height above.
68
+
69
+ - d1eef08: The style contract gains nineteen optional names for the parts of greptile.com's own components that no earlier round measured (looks-fidelity round 6, spec §11, Zine's lane R6.Z). Each is `initial` on the shared `[data-style]` reset, `console` declines it, and each reader falls back to exactly what its component drew, so under no set and under every set that does not name it nothing moves. The `zine` set declares them.
70
+
71
+ - **Disclosures** (`Accordion`, `Collapsible`, `Disclosure`): `--cue-style-collapse-weight`, `-collapse-caret-size`, `-collapse-caret-ink`, `-collapse-body-size`, `-collapse-body-leading`, `-collapse-body-tracking`; and the inline disclosure's `--cue-style-disclosure-ink`, `-disclosure-hover-ink` and `-disclosure-weight`.
72
+ - **Tooltip**: `--cue-style-tooltip-face`, `-tooltip-ink`, `-tooltip-leading`.
73
+ - **Breadcrumb**: `--cue-style-crumb-face`, `-crumb-hover-ink`, `-crumb-gap`, `-crumb-ink`, `-crumb-size`.
74
+ - **Avatar**: `--cue-style-avatar-radius` and `-avatar-edge`.
75
+
76
+ Two names from the round's lanes are gone again before release: `--cue-style-invalid-edge` and `--cue-style-collapse-body-face`, which no set spent (spec §3.0 adds a name only when a set spends it). The chassis's invalid edge is `danger` again and a disclosure panel's body reads the body face.
77
+
78
+ ### Patch Changes
79
+
80
+ - Updated dependencies [d1eef08]
81
+ - Updated dependencies [d1eef08]
82
+ - Updated dependencies [d1eef08]
83
+ - Updated dependencies [d1eef08]
84
+ - Updated dependencies [d1eef08]
85
+ - @cueplusplus/tokens@0.18.0
86
+
3
87
  ## 0.17.0
4
88
 
5
89
  ### Minor Changes
@@ -1,4 +1,8 @@
1
1
  import { cn } from "../lib/cn.js";
2
+ import { GLYPH_INK_SUBTLE } from "../system/_style-glyph-ink.js";
3
+ import { BODY_LEADING } from "../system/_style-body-leading.js";
4
+ import { BODY_SIZE } from "../system/_style-body-size.js";
5
+ import { EMPTY_GAP, EMPTY_HINT_VOICE, EMPTY_ICON_SIZE, EMPTY_PAD, EMPTY_TITLE_FACE, EMPTY_TITLE_LEADING, EMPTY_TITLE_SIZE, EMPTY_TITLE_WEIGHT } from "../system/_style-empty-state.js";
2
6
  import * as React from "react";
3
7
  import { jsx, jsxs } from "react/jsx-runtime";
4
8
  //#region src/chrome/empty-state.tsx
@@ -26,22 +30,22 @@ const EmptyState = React.forwardRef(function EmptyState({ className, title, hint
26
30
  return /* @__PURE__ */ jsxs("div", {
27
31
  ref,
28
32
  "data-slot": "empty-state",
29
- className: cn("flex flex-col items-center justify-center gap-(--cue-space-3) px-(--cue-space-6) py-(--cue-space-7) text-center font-mono", className),
33
+ className: cn(`flex flex-col items-center justify-center ${EMPTY_GAP} px-(--cue-space-6) ${EMPTY_PAD} text-center font-mono`, className),
30
34
  ...elementProps,
31
35
  children: [
32
36
  Icon === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
33
37
  "aria-hidden": "true",
34
38
  "data-slot": "empty-state-icon",
35
- className: "size-(--cue-space-7) shrink-0 text-fg-subtle"
39
+ className: `${EMPTY_ICON_SIZE} shrink-0 ${GLYPH_INK_SUBTLE}`
36
40
  }),
37
41
  /* @__PURE__ */ jsx("span", {
38
42
  "data-slot": "empty-state-title",
39
- className: "text-(length:--cue-text-emphasis) text-fg",
43
+ className: `${EMPTY_TITLE_FACE} ${EMPTY_TITLE_SIZE} ${EMPTY_TITLE_WEIGHT} ${EMPTY_TITLE_LEADING} text-fg`,
40
44
  children: title
41
45
  }),
42
46
  hint === void 0 ? null : /* @__PURE__ */ jsx("p", {
43
47
  "data-slot": "empty-state-hint",
44
- className: "max-w-[36ch] text-(length:--cue-text-ui) leading-(--cue-leading-ui) text-fg-muted",
48
+ className: `max-w-[36ch] ${EMPTY_HINT_VOICE} ${BODY_SIZE} ${BODY_LEADING} text-fg-muted`,
45
49
  children: hint
46
50
  }),
47
51
  children,
@@ -5,6 +5,7 @@ import { CONTROL_FACE } from "../system/_style-control-face.js";
5
5
  import { CaretDownGlyph } from "./_glyphs.js";
6
6
  import { useCuePortalProps } from "../system/portal.js";
7
7
  import { overlayPopupTransitionClasses, overlayPositionerClasses, overlaySurfaceClasses } from "../overlays/_surface.js";
8
+ import { NAV_CARET_INK, NAV_OPEN_GROUND, NAV_TRIGGER_HEIGHT, NAV_TRIGGER_HOVER_INK, NAV_TRIGGER_INK, NAV_TRIGGER_PAD, NAV_TRIGGER_VOICE } from "../system/_style-nav-menu.js";
8
9
  import * as React from "react";
9
10
  import { jsx, jsxs } from "react/jsx-runtime";
10
11
  import { NavigationMenu } from "@base-ui/react/navigation-menu";
@@ -66,11 +67,11 @@ const NavigationMenu$1 = {
66
67
  return /* @__PURE__ */ jsxs(NavigationMenu.Trigger, {
67
68
  ref,
68
69
  "data-slot": "navigation-menu-trigger",
69
- className: cn(`inline-flex h-control-md cursor-default items-center gap-(--cue-space-2) rounded-control px-(--cue-space-3) text-(length:--cue-text-ui) whitespace-nowrap text-fg-muted no-underline transition-colors duration-150 outline-none select-none hover:text-fg ${FOCUS_RING_INSET} data-[popup-open]:bg-accent-soft data-[popup-open]:text-fg`, CONTROL_FACE, className),
70
+ className: cn(`inline-flex ${NAV_TRIGGER_HEIGHT} cursor-default items-center gap-(--cue-space-2) rounded-control ${NAV_TRIGGER_PAD} ${NAV_TRIGGER_VOICE} whitespace-nowrap ${NAV_TRIGGER_INK} no-underline transition-colors duration-150 outline-none select-none ${NAV_TRIGGER_HOVER_INK} ${FOCUS_RING_INSET} ${NAV_OPEN_GROUND} data-[popup-open]:text-fg`, className),
70
71
  ...elementProps,
71
72
  children: [children, caret ? /* @__PURE__ */ jsx(NavigationMenu.Icon, {
72
73
  className: "flex items-center transition-transform duration-150 data-[popup-open]:rotate-180 motion-reduce:transition-none",
73
- children: /* @__PURE__ */ jsx(CaretDownGlyph, { className: "size-icon-sm text-fg-subtle" })
74
+ children: /* @__PURE__ */ jsx(CaretDownGlyph, { className: `size-icon-sm ${NAV_CARET_INK}` })
74
75
  }) : null]
75
76
  });
76
77
  }),
@@ -1,4 +1,5 @@
1
1
  import { cn } from "../lib/cn.js";
2
+ import { PANEL_PAD_X, PANEL_PAD_Y, PANEL_RULE } from "../system/_style-panel.js";
2
3
  import { RIM_INSET } from "../system/_paint-rim.js";
3
4
  import { TITLE_VOICE } from "../system/_style-title.js";
4
5
  import * as React from "react";
@@ -52,7 +53,7 @@ const PanelHeader = React.forwardRef(function PanelHeader({ className, title, ac
52
53
  return /* @__PURE__ */ jsxs("div", {
53
54
  ref,
54
55
  "data-slot": "panel-header",
55
- className: cn("flex items-center justify-between gap-(--cue-space-3) border-b border-border px-(--cue-pad-row-x) py-(--cue-pad-row-y)", className),
56
+ className: cn(`flex items-center justify-between gap-(--cue-space-3) border-b ${PANEL_RULE} ${PANEL_PAD_X} ${PANEL_PAD_Y}`, className),
56
57
  ...elementProps,
57
58
  children: [/* @__PURE__ */ jsxs("div", {
58
59
  className: "flex min-w-0 items-center gap-(--cue-space-3)",
@@ -2,6 +2,7 @@ import { cn } from "../lib/cn.js";
2
2
  import { FOCUS_RING_INSET_2 } from "../system/_focus-ring.js";
3
3
  import { cva } from "../lib/cva.js";
4
4
  import { DATA_FACE } from "../system/_style-data-face.js";
5
+ import { ROW_BLOCK_PAD, ROW_INK, ROW_RULE_STYLE } from "../system/_style-row.js";
5
6
  import { SEAM_INK, SEAM_RIM } from "../system/_style-seam.js";
6
7
  import * as React from "react";
7
8
  import { jsx } from "react/jsx-runtime";
@@ -21,11 +22,11 @@ import { jsx } from "react/jsx-runtime";
21
22
  * @example
22
23
  * <li className={rowVariants({ interactive: true })} />
23
24
  */
24
- const rowVariants = cva(`flex w-full items-center gap-(--cue-space-3) px-(--cue-pad-row-x) py-(--cue-pad-row-y) ${DATA_FACE} text-(length:--cue-text-ui) text-fg`, {
25
+ const rowVariants = cva(`flex w-full items-center gap-(--cue-space-3) px-(--cue-pad-row-x) ${DATA_FACE} text-(length:--cue-text-ui) ${ROW_INK}`, {
25
26
  variants: {
26
27
  seam: {
27
- true: "bg-bg",
28
- false: "border-t border-border first:border-t-0 [[data-slot=panel-header]+&]:border-t-0"
28
+ true: "bg-bg py-(--cue-pad-row-y)",
29
+ false: `border-t border-border first:border-t-0 [[data-slot=panel-header]+&]:border-t-0 ${ROW_RULE_STYLE} ${ROW_BLOCK_PAD}`
29
30
  },
30
31
  interactive: {
31
32
  true: `cursor-pointer text-left transition-colors duration-150 outline-none hover:bg-surface-2 ${FOCUS_RING_INSET_2} disabled:pointer-events-none disabled:opacity-40`,
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { FOCUS_RING_INSET_2 } from "../system/_focus-ring.js";
4
+ import { SCROLLBAR_SIZE_H, SCROLLBAR_SIZE_V, SCROLLBAR_THUMB } from "../system/_style-scrollbar.js";
4
5
  import * as React from "react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  import { ScrollArea } from "@base-ui/react/scroll-area";
@@ -11,7 +12,7 @@ import { ScrollArea } from "@base-ui/react/scroll-area";
11
12
  * A console packs panels edge to edge, and a permanent 12px trough on every one
12
13
  * of them is 12px of chrome per panel that says nothing.
13
14
  */
14
- const SCROLLBAR_CLASSES = "flex touch-none justify-center rounded-full opacity-0 transition-opacity delay-300 duration-150 select-none data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0 motion-reduce:transition-none data-[orientation=horizontal]:h-(--cue-space-3) data-[orientation=horizontal]:flex-col data-[orientation=vertical]:w-(--cue-space-3)";
15
+ const SCROLLBAR_CLASSES = `flex touch-none justify-center rounded-full opacity-0 transition-opacity delay-300 duration-150 select-none data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0 motion-reduce:transition-none ${SCROLLBAR_SIZE_H} data-[orientation=horizontal]:flex-col ${SCROLLBAR_SIZE_V}`;
15
16
  /**
16
17
  * A scrolling region with the system's own scrollbar instead of the platform's.
17
18
  *
@@ -50,7 +51,7 @@ const ScrollArea$1 = React.forwardRef(function ScrollArea$2({ className, viewpor
50
51
  className: SCROLLBAR_CLASSES,
51
52
  children: /* @__PURE__ */ jsx(ScrollArea.Thumb, {
52
53
  "data-slot": "scroll-area-thumb",
53
- className: "w-full rounded-full bg-border-strong"
54
+ className: `w-full rounded-full ${SCROLLBAR_THUMB}`
54
55
  })
55
56
  }) : null,
56
57
  horizontal ? /* @__PURE__ */ jsx(ScrollArea.Scrollbar, {
@@ -60,7 +61,7 @@ const ScrollArea$1 = React.forwardRef(function ScrollArea$2({ className, viewpor
60
61
  className: SCROLLBAR_CLASSES,
61
62
  children: /* @__PURE__ */ jsx(ScrollArea.Thumb, {
62
63
  "data-slot": "scroll-area-thumb",
63
- className: "h-full rounded-full bg-border-strong"
64
+ className: `h-full rounded-full ${SCROLLBAR_THUMB}`
64
65
  })
65
66
  }) : null,
66
67
  vertical && horizontal ? /* @__PURE__ */ jsx(ScrollArea.Corner, { "data-slot": "scroll-area-corner" }) : null
@@ -4,6 +4,7 @@ import { FOCUS_RING_INSET } from "../system/_focus-ring.js";
4
4
  import { CONTROL_FACE } from "../system/_style-control-face.js";
5
5
  import { useComposedRefs } from "../lib/compose.js";
6
6
  import { EDGE_SCROLLER_CLASSES, EdgeChevrons, useEdgeScroll } from "./_edge-scroller.js";
7
+ import { SEGMENT_PAD } from "../system/_style-segment-pad.js";
7
8
  import { SEGMENT_IDLE_INK } from "../system/_style-segment.js";
8
9
  import { SEGMENTED_CHEVRON_GROUND, SEGMENTED_RIM, SEGMENTED_TRACK, SEGMENT_PRESSED, SEGMENT_RADIUS } from "../system/_style-segmented-control.js";
9
10
  import * as React from "react";
@@ -13,7 +14,7 @@ import { ToggleGroup } from "@base-ui/react/toggle-group";
13
14
  //#region src/chrome/segmented-control.tsx
14
15
  const ITEM_SIZES = {
15
16
  sm: "h-control-sm px-(--cue-space-3) text-(length:--cue-text-label)",
16
- md: "h-control-md px-(--cue-space-4) text-(length:--cue-text-ui)",
17
+ md: `h-control-md ${SEGMENT_PAD} text-(length:--cue-text-ui)`,
17
18
  lg: "h-control-lg px-(--cue-space-5) text-(length:--cue-text-body)"
18
19
  };
19
20
  /**
@@ -3,7 +3,10 @@ import { cn } from "../lib/cn.js";
3
3
  import { FOCUS_RING_INSET_2, FOCUS_RING_OFFSET_2 } from "../system/_focus-ring.js";
4
4
  import { CONTROL_FACE } from "../system/_style-control-face.js";
5
5
  import { EDGE_SCROLLER_CLASSES, EdgeChevrons, useEdgeScroll } from "./_edge-scroller.js";
6
+ import { SEGMENT_PAD } from "../system/_style-segment-pad.js";
6
7
  import { SEGMENT_IDLE_INK } from "../system/_style-segment.js";
8
+ import { TAB_HOVER_INK } from "../system/_style-tab-hover.js";
9
+ import { GROUP_GAP } from "../system/_style-group-gap.js";
7
10
  import { TAB_ACTIVE, TAB_RULE, TAB_SHAPE, TAB_TRACK, TAB_UNDERLINE } from "../system/_style-tab.js";
8
11
  import * as React from "react";
9
12
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -29,7 +32,7 @@ const TabsList = React.forwardRef(function TabsList({ className, ...elementProps
29
32
  return /* @__PURE__ */ jsx(Tabs.List, {
30
33
  ref,
31
34
  "data-slot": "tabs-list",
32
- className: cn(`relative flex items-center gap-(--cue-space-1) ${TAB_RULE} border-border ${TAB_TRACK} data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch data-[orientation=vertical]:border-b-0 data-[orientation=vertical]:border-r`, className),
35
+ className: cn(`relative flex items-center ${GROUP_GAP} ${TAB_RULE} border-border ${TAB_TRACK} data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch data-[orientation=vertical]:border-b-0 data-[orientation=vertical]:border-r`, className),
33
36
  ...elementProps
34
37
  });
35
38
  });
@@ -46,7 +49,7 @@ const TabsTab = React.forwardRef(function TabsTab({ className, ...elementProps }
46
49
  return /* @__PURE__ */ jsx(Tabs.Tab, {
47
50
  ref,
48
51
  "data-slot": "tabs-tab",
49
- className: cn(`relative inline-flex h-control-md shrink-0 cursor-pointer items-center justify-center gap-(--cue-space-2) ${TAB_SHAPE} px-(--cue-space-4) text-(length:--cue-text-ui) whitespace-nowrap ${SEGMENT_IDLE_INK} transition-colors duration-150 outline-none select-none`, CONTROL_FACE, `hover:text-fg ${FOCUS_RING_INSET_2}`, "data-[disabled]:pointer-events-none data-[disabled]:opacity-40", "after:absolute after:inset-x-0 after:-bottom-px after:h-px after:bg-transparent after:content-['']", `${TAB_ACTIVE} ${TAB_UNDERLINE}`, className),
52
+ className: cn(`relative inline-flex h-control-md shrink-0 cursor-pointer items-center justify-center gap-(--cue-space-2) ${TAB_SHAPE} ${SEGMENT_PAD} text-(length:--cue-text-ui) whitespace-nowrap ${SEGMENT_IDLE_INK} transition-colors duration-150 outline-none select-none`, CONTROL_FACE, `${TAB_HOVER_INK} ${FOCUS_RING_INSET_2}`, "data-[disabled]:pointer-events-none data-[disabled]:opacity-40", "after:absolute after:inset-x-0 after:-bottom-px after:h-px after:bg-transparent after:content-['']", `${TAB_ACTIVE} ${TAB_UNDERLINE}`, className),
50
53
  ...elementProps
51
54
  });
52
55
  });
@@ -1,8 +1,10 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { FOCUS_RING_INSET } from "../system/_focus-ring.js";
4
+ import { GHOST_INK } from "../system/_style-control.js";
4
5
  import { useComposedRefs } from "../lib/compose.js";
5
6
  import { EDGE_SCROLLER_CLASSES, EdgeChevrons, useEdgeScroll } from "./_edge-scroller.js";
7
+ import { TOOLBAR_FRAME, TOOLBAR_SEPARATOR_HEIGHT } from "../system/_style-toolbar.js";
6
8
  import * as React from "react";
7
9
  import { jsx, jsxs } from "react/jsx-runtime";
8
10
  import { Toolbar } from "@base-ui/react/toolbar";
@@ -31,7 +33,7 @@ const Toolbar$1 = {
31
33
  const bar = /* @__PURE__ */ jsx(Toolbar.Root, {
32
34
  ref: barRef,
33
35
  "data-slot": "toolbar",
34
- className: cn("flex h-(--cue-chrome-toolbar) w-full shrink-0 items-center gap-(--cue-space-2) border-b border-border bg-surface-1 px-(--cue-pad-row-x) data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-(--cue-chrome-toolbar) data-[orientation=vertical]:flex-col data-[orientation=vertical]:border-r data-[orientation=vertical]:border-b-0", scrolls ? EDGE_SCROLLER_CLASSES : null, className),
36
+ className: cn(`flex w-full shrink-0 items-center border-b ${TOOLBAR_FRAME} bg-surface-1 data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-(--cue-chrome-toolbar) data-[orientation=vertical]:flex-col data-[orientation=vertical]:border-r data-[orientation=vertical]:border-b-0`, scrolls ? EDGE_SCROLLER_CLASSES : null, className),
35
37
  ...elementProps,
36
38
  style: {
37
39
  ...elementProps.style,
@@ -55,7 +57,7 @@ const Toolbar$1 = {
55
57
  return /* @__PURE__ */ jsxs(Toolbar.Button, {
56
58
  ref,
57
59
  "data-slot": "toolbar-button",
58
- className: cn(`inline-flex h-control-md shrink-0 cursor-pointer items-center justify-center gap-(--cue-space-2) rounded-control px-(--cue-space-3) font-mono text-(length:--cue-text-ui) whitespace-nowrap text-fg-muted transition-colors duration-150 outline-none select-none hover:bg-surface-2 hover:text-fg ${FOCUS_RING_INSET} data-[disabled]:pointer-events-none data-[disabled]:opacity-40`, className),
60
+ className: cn(`inline-flex h-control-md shrink-0 cursor-pointer items-center justify-center gap-(--cue-space-2) rounded-control px-(--cue-space-3) font-mono text-(length:--cue-text-ui) whitespace-nowrap ${GHOST_INK} transition-colors duration-150 outline-none select-none hover:bg-surface-2 hover:text-fg ${FOCUS_RING_INSET} data-[disabled]:pointer-events-none data-[disabled]:opacity-40`, className),
59
61
  ...elementProps,
60
62
  children: [Icon === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
61
63
  "aria-hidden": "true",
@@ -75,7 +77,7 @@ const Toolbar$1 = {
75
77
  return /* @__PURE__ */ jsx(Toolbar.Separator, {
76
78
  ref,
77
79
  "data-slot": "toolbar-separator",
78
- className: cn("shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:mx-(--cue-space-1) data-[orientation=vertical]:h-[60%] data-[orientation=vertical]:w-px", className),
80
+ className: cn(`shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:mx-(--cue-space-1) ${TOOLBAR_SEPARATOR_HEIGHT} data-[orientation=vertical]:w-px`, className),
79
81
  ...elementProps
80
82
  });
81
83
  })
@@ -4,6 +4,13 @@ import * as React from "react";
4
4
  import { ColorFieldProps, InputProps } from "react-aria-components";
5
5
  //#region src/color/color-field.d.ts
6
6
  interface ColorFieldProps$1 extends Omit<ColorFieldProps, "children"> {
7
+ /**
8
+ * The field's accessible name. `ColorField` draws no visible label — React
9
+ * Aria's label slot is left empty — so name it here, or point
10
+ * `aria-labelledby` at a label of your own. Without either the input has no
11
+ * name at all.
12
+ */
13
+ "aria-label"?: string;
7
14
  /** Rung of the control ladder. Defaults to `"md"`. */
8
15
  size?: FormControlSize;
9
16
  /** Extra classes for the input itself. */
@@ -1,5 +1,8 @@
1
1
  import { cn } from "../lib/cn.js";
2
2
  import { controlVariants } from "../forms/_chassis.js";
3
+ import { GLYPH_INK_SUBTLE } from "../system/_style-glyph-ink.js";
4
+ import { GLYPH_OPACITY } from "../system/_style-glyph-opacity.js";
5
+ import { GLYPH_SIZE } from "../system/_style-glyph-size.js";
3
6
  //#region src/date/_trigger.ts
4
7
  /**
5
8
  * The shared skin of the two popover-backed date controls, `DatePicker` and
@@ -24,7 +27,7 @@ const dateTriggerValueClasses = "truncate tabular-nums";
24
27
  /** Placeholder ink, applied to the readout when there is nothing to read. */
25
28
  const dateTriggerPlaceholderClasses = "text-fg-subtle";
26
29
  /** The trailing glyph — never a control, so it never takes the pointer. */
27
- const dateTriggerGlyphClasses = "size-icon-sm shrink-0 text-fg-subtle";
30
+ const dateTriggerGlyphClasses = `${GLYPH_SIZE} shrink-0 ${GLYPH_INK_SUBTLE} ${GLYPH_OPACITY}`;
28
31
  /** Padding of the popup around a calendar: one unit tighter than a popover's. */
29
32
  const datePopupClasses = "p-(--cue-space-3)";
30
33
  //#endregion
@@ -1,9 +1,14 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { FOCUS_RING } from "../system/_focus-ring.js";
4
+ import { GLYPH_INK_SUBTLE } from "../system/_style-glyph-ink.js";
5
+ import { GLYPH_OPACITY } from "../system/_style-glyph-opacity.js";
4
6
  import { LABEL_FACE } from "../system/_style-label-face.js";
5
7
  import { LABEL_CASE } from "../system/_style-label-case.js";
6
8
  import { LABEL_TRACKING, LABEL_TRACKING_TIGHT } from "../system/_style-label-tracking.js";
9
+ import { CAPTION_SIZE_LABEL, CAPTION_SIZE_MICRO } from "../system/_style-caption-size.js";
10
+ import { CAPTION_WEIGHT, CAPTION_WEIGHT_NORMAL } from "../system/_style-caption-weight.js";
11
+ import { DAY_HEIGHT, DAY_INK, DAY_SIZE } from "../system/_style-day.js";
7
12
  import "react";
8
13
  import { jsx } from "react/jsx-runtime";
9
14
  import { DayPicker } from "react-day-picker";
@@ -14,7 +19,8 @@ import { DayPicker } from "react-day-picker";
14
19
  * react-day-picker ships its own stylesheet; this system never loads it. Each
15
20
  * key below is one `UI` / `DayFlag` / `SelectionState` slot, dressed from the
16
21
  * same tokens as the rest of the kit: the day cell is one rung of the control
17
- * ladder (`size-control-sm`), the caption is a mono micro label, the selected
22
+ * ladder (`size-control-sm`, or a set's `style-day-size`, which the month-nav
23
+ * buttons and the caption row share), the caption is a mono micro label, the selected
18
24
  * day takes the solid accent and a range's middle takes `accent-soft` — the
19
25
  * same "soft tint for a span, solid for the thing you picked" rule the menus
20
26
  * use.
@@ -26,18 +32,18 @@ const CALENDAR_CLASSES = {
26
32
  root: "font-mono text-(length:--cue-text-ui) text-fg",
27
33
  months: "relative flex flex-wrap items-start gap-(--cue-space-5)",
28
34
  month: "flex flex-col gap-(--cue-space-2)",
29
- month_caption: "flex h-control-sm items-center justify-center",
30
- caption_label: `${LABEL_FACE} text-(length:--cue-text-label) ${LABEL_TRACKING} text-fg-subtle ${LABEL_CASE}`,
31
- nav: "absolute inset-x-0 top-0 flex h-control-sm items-center justify-between",
32
- button_previous: `flex size-control-sm cursor-pointer items-center justify-center rounded-control border-0 bg-transparent p-0 text-fg-subtle outline-none transition-colors duration-150 hover:text-fg ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-30 motion-reduce:transition-none`,
33
- button_next: `flex size-control-sm cursor-pointer items-center justify-center rounded-control border-0 bg-transparent p-0 text-fg-subtle outline-none transition-colors duration-150 hover:text-fg ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-30 motion-reduce:transition-none`,
34
- chevron: "size-icon-sm fill-current",
35
+ month_caption: `flex ${DAY_HEIGHT} items-center justify-center`,
36
+ caption_label: `${LABEL_FACE} ${CAPTION_SIZE_LABEL} ${CAPTION_WEIGHT} ${LABEL_TRACKING} text-fg-subtle ${LABEL_CASE}`,
37
+ nav: `absolute inset-x-0 top-0 flex ${DAY_HEIGHT} items-center justify-between`,
38
+ button_previous: `flex ${DAY_SIZE} cursor-pointer items-center justify-center rounded-control border-0 bg-transparent p-0 ${GLYPH_INK_SUBTLE} outline-none transition-colors duration-150 hover:text-fg ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-30 motion-reduce:transition-none`,
39
+ button_next: `flex ${DAY_SIZE} cursor-pointer items-center justify-center rounded-control border-0 bg-transparent p-0 ${GLYPH_INK_SUBTLE} outline-none transition-colors duration-150 hover:text-fg ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-30 motion-reduce:transition-none`,
40
+ chevron: `size-icon-sm fill-current ${GLYPH_OPACITY}`,
35
41
  month_grid: "border-collapse border-spacing-0",
36
42
  weekdays: "",
37
- weekday: `size-control-sm p-0 text-center align-middle ${LABEL_FACE} text-(length:--cue-text-micro) font-normal ${LABEL_TRACKING_TIGHT} text-fg-subtle ${LABEL_CASE}`,
43
+ weekday: `${DAY_SIZE} p-0 text-center align-middle ${LABEL_FACE} ${CAPTION_SIZE_MICRO} ${CAPTION_WEIGHT_NORMAL} ${LABEL_TRACKING_TIGHT} text-fg-subtle ${LABEL_CASE}`,
38
44
  week: "",
39
45
  day: "p-0 text-center align-middle",
40
- day_button: `size-control-sm cursor-pointer rounded-control border-0 bg-transparent p-0 font-mono text-(length:--cue-text-ui) tabular-nums text-fg-muted outline-none transition-colors duration-150 hover:bg-surface-3 hover:text-fg ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-30 motion-reduce:transition-none`,
46
+ day_button: `${DAY_SIZE} cursor-pointer rounded-control border-0 bg-transparent p-0 font-mono text-(length:--cue-text-ui) tabular-nums ${DAY_INK} outline-none transition-colors duration-150 hover:bg-surface-3 hover:text-fg ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-30 motion-reduce:transition-none`,
41
47
  today: "[&_button]:font-medium [&_button]:ring-1 [&_button]:ring-inset [&_button]:ring-accent/60",
42
48
  outside: "[&_button]:text-fg-subtle [&_button]:opacity-50",
43
49
  disabled: "opacity-40",
@@ -110,7 +110,7 @@ import { FormControlSize } from "./_chassis-size.js";
110
110
  * own `shadow-` utility replaces it through `twMerge`, as it would have
111
111
  * replaced nothing before.
112
112
  */
113
- declare const controlSurface = "w-full rounded-control border-transparent border-(length:--cue-paint-stroke-width) bg-[linear-gradient(var(--cue-sunken),var(--cue-sunken)),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border)),var(--cue-paint-stroke-to,var(--cue-border)))] bg-origin-border [background-clip:padding-box,border-box] shadow-[shadow:0_calc(2px*var(--cue-paint-shadow-scale))_calc(4px*var(--cue-paint-shadow-scale))_var(--cue-paint-rest-shade,transparent)] font-[family-name:var(--cue-style-input-face,var(--cue-font-mono))] font-[number:var(--cue-style-body-weight,inherit)] text-fg placeholder:text-fg-subtle outline-none focus:border-[color:var(--cue-style-focus-edge,var(--cue-border-strong))] focus-visible:outline-solid focus-visible:outline-[length:var(--cue-style-focus-width,var(--cue-focus-ring))] focus-visible:outline-(--cue-focus) focus-visible:outline-offset-[var(--cue-style-field-focus-offset,-1px)] disabled:opacity-40 data-[disabled]:opacity-40 data-[invalid]:border-danger data-[invalid]:focus-visible:outline-danger";
113
+ declare const controlSurface = "w-full rounded-control border-transparent border-(length:--cue-paint-stroke-width) bg-[linear-gradient(var(--cue-sunken),var(--cue-sunken)),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border)),var(--cue-paint-stroke-to,var(--cue-border)))] bg-origin-border [background-clip:padding-box,border-box] shadow-[shadow:0_calc(2px*var(--cue-paint-shadow-scale))_calc(4px*var(--cue-paint-shadow-scale))_var(--cue-paint-rest-shade,transparent)] font-[family-name:var(--cue-style-input-face,var(--cue-font-mono))] font-[number:var(--cue-style-body-weight,inherit)] text-fg placeholder:text-fg-subtle outline-none hover:border-[color:var(--cue-style-field-hover-edge,transparent)] focus:border-[color:var(--cue-style-focus-edge,var(--cue-border-strong))] focus-visible:outline-solid focus-visible:outline-[length:var(--cue-style-focus-width,var(--cue-focus-ring))] focus-visible:outline-(--cue-focus) focus-visible:outline-offset-[var(--cue-style-field-focus-offset,-1px)] disabled:opacity-[var(--cue-style-disabled-opacity,0.4)] data-[disabled]:opacity-[var(--cue-style-disabled-opacity,0.4)] disabled:bg-[linear-gradient(var(--cue-style-disabled-fill,var(--cue-sunken)),var(--cue-style-disabled-fill,var(--cue-sunken))),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border)),var(--cue-paint-stroke-to,var(--cue-border)))] data-[disabled]:bg-[linear-gradient(var(--cue-style-disabled-fill,var(--cue-sunken)),var(--cue-style-disabled-fill,var(--cue-sunken))),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border)),var(--cue-paint-stroke-to,var(--cue-border)))] data-[invalid]:border-danger data-[invalid]:focus-visible:outline-danger";
114
114
  /**
115
115
  * The full recessed-control recipe, one variant per rung of the control ladder.
116
116
  *
@@ -171,7 +171,15 @@ declare const bareControlClasses = "min-w-0 flex-1 border-0 bg-transparent p-0 f
171
171
  * still visible. `data-invalid` is read off the wrapper, which is where Base
172
172
  * UI's `Field` stamps it and where the group already takes
173
173
  * `data-[invalid]:border-danger` from {@link controlVariants}.
174
+ *
175
+ * The rim is `has-focus:`, not `focus-within:`, for the order Tailwind emits
176
+ * them in: `focus-within:` comes before `hover:` and `has-focus:` after it, both
177
+ * before `data-[invalid]:`. Round 6 gave the chassis a hover edge
178
+ * (`FIELD_HOVER_EDGE`, `transparent` unless a set names one), and under the
179
+ * pointer it painted over a focused group's rim in every Look; the closing
180
+ * pass's browser run caught it (`form-focus.spec.ts`, a grouped field). The
181
+ * wrapper never takes focus itself, so `:has(:focus)` is the same test.
174
182
  */
175
- declare const controlGroupFocusClasses = "focus-within:border-border-strong has-focus-visible:outline-solid has-focus-visible:outline-[length:var(--cue-style-focus-width,var(--cue-focus-ring))] has-focus-visible:outline-(--cue-focus) has-focus-visible:outline-offset-[var(--cue-style-field-focus-offset,-1px)] data-[invalid]:has-focus-visible:outline-danger";
183
+ declare const controlGroupFocusClasses = "has-focus:border-border-strong has-focus-visible:outline-solid has-focus-visible:outline-[length:var(--cue-style-focus-width,var(--cue-focus-ring))] has-focus-visible:outline-(--cue-focus) has-focus-visible:outline-offset-[var(--cue-style-field-focus-offset,-1px)] data-[invalid]:has-focus-visible:outline-danger";
176
184
  //#endregion
177
185
  export { ControlVariantProps, type FormControlSize, bareControlClasses, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants };
@@ -1,9 +1,11 @@
1
1
  import { REST_SHADE_CLASS } from "../system/_paint-rest-shade.js";
2
+ import { DATA_DISABLED_OPACITY, DISABLED_OPACITY, FIELD_DISABLED_FILL } from "../system/_style-disabled.js";
2
3
  import { cva } from "../lib/cva.js";
3
4
  import { FOCUS_RING_FIELD, FOCUS_RING_GROUP_FIELD } from "../system/_focus-ring-field.js";
4
5
  import { CONTROL_STEP_SIZE_BODY, CONTROL_STEP_SIZE_SM } from "../system/_style-control-step.js";
5
6
  import { STROKE_SUNKEN } from "../system/_paint-stroke-sunken.js";
6
7
  import { BODY_WEIGHT } from "../system/_style-body-weight.js";
8
+ import { FIELD_HOVER_EDGE, FIELD_PAD_LG, FIELD_PAD_MD, FIELD_PAD_SM, INVALID_EDGE } from "../system/_style-field-chassis.js";
7
9
  import { INPUT_FACE } from "../system/_style-input-face.js";
8
10
  //#region src/forms/_chassis.ts
9
11
  /**
@@ -115,7 +117,7 @@ import { INPUT_FACE } from "../system/_style-input-face.js";
115
117
  * own `shadow-` utility replaces it through `twMerge`, as it would have
116
118
  * replaced nothing before.
117
119
  */
118
- const controlSurface = `w-full rounded-control ${STROKE_SUNKEN} ${REST_SHADE_CLASS} ${INPUT_FACE} ${BODY_WEIGHT} text-fg placeholder:text-fg-subtle outline-none focus:border-[color:var(--cue-style-focus-edge,var(--cue-border-strong))] ${FOCUS_RING_FIELD} disabled:opacity-40 data-[disabled]:opacity-40 data-[invalid]:border-danger data-[invalid]:focus-visible:outline-danger`;
120
+ const controlSurface = `w-full rounded-control ${STROKE_SUNKEN} ${REST_SHADE_CLASS} ${INPUT_FACE} ${BODY_WEIGHT} text-fg placeholder:text-fg-subtle outline-none ${FIELD_HOVER_EDGE} focus:border-[color:var(--cue-style-focus-edge,var(--cue-border-strong))] ${FOCUS_RING_FIELD} ${DISABLED_OPACITY} ${DATA_DISABLED_OPACITY} ${FIELD_DISABLED_FILL} ${INVALID_EDGE} data-[invalid]:focus-visible:outline-danger`;
119
121
  /**
120
122
  * The full recessed-control recipe, one variant per rung of the control ladder.
121
123
  *
@@ -128,9 +130,9 @@ const controlSurface = `w-full rounded-control ${STROKE_SUNKEN} ${REST_SHADE_CLA
128
130
  */
129
131
  const controlVariants = cva(controlSurface, {
130
132
  variants: { size: {
131
- sm: `h-control-sm px-(--cue-space-3) ${CONTROL_STEP_SIZE_SM}`,
132
- md: "h-control-md px-(--cue-space-4) text-(length:--cue-text-ui)",
133
- lg: `h-control-lg px-(--cue-space-5) ${CONTROL_STEP_SIZE_BODY}`
133
+ sm: `h-control-sm ${FIELD_PAD_SM} ${CONTROL_STEP_SIZE_SM}`,
134
+ md: `h-control-md ${FIELD_PAD_MD} text-(length:--cue-text-ui)`,
135
+ lg: `h-control-lg ${FIELD_PAD_LG} ${CONTROL_STEP_SIZE_BODY}`
134
136
  } },
135
137
  defaultVariants: { size: "md" }
136
138
  });
@@ -179,7 +181,15 @@ const bareControlClasses = `min-w-0 flex-1 border-0 bg-transparent p-0 ${INPUT_F
179
181
  * still visible. `data-invalid` is read off the wrapper, which is where Base
180
182
  * UI's `Field` stamps it and where the group already takes
181
183
  * `data-[invalid]:border-danger` from {@link controlVariants}.
184
+ *
185
+ * The rim is `has-focus:`, not `focus-within:`, for the order Tailwind emits
186
+ * them in: `focus-within:` comes before `hover:` and `has-focus:` after it, both
187
+ * before `data-[invalid]:`. Round 6 gave the chassis a hover edge
188
+ * (`FIELD_HOVER_EDGE`, `transparent` unless a set names one), and under the
189
+ * pointer it painted over a focused group's rim in every Look; the closing
190
+ * pass's browser run caught it (`form-focus.spec.ts`, a grouped field). The
191
+ * wrapper never takes focus itself, so `:has(:focus)` is the same test.
182
192
  */
183
- const controlGroupFocusClasses = `focus-within:border-border-strong ${FOCUS_RING_GROUP_FIELD} data-[invalid]:has-focus-visible:outline-danger`;
193
+ const controlGroupFocusClasses = `has-focus:border-border-strong ${FOCUS_RING_GROUP_FIELD} data-[invalid]:has-focus-visible:outline-danger`;
184
194
  //#endregion
185
195
  export { bareControlClasses, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants };
@@ -1,7 +1,12 @@
1
1
  import { FOCUS_RING } from "../system/_focus-ring.js";
2
2
  import { CONTROL_FACE } from "../system/_style-control-face.js";
3
+ import { GLYPH_INK_SUBTLE } from "../system/_style-glyph-ink.js";
4
+ import { GLYPH_OPACITY_SVG } from "../system/_style-glyph-opacity.js";
5
+ import { CHIP_HEIGHT, CHIP_INK_NEUTRAL, CHIP_RADIUS, CHIP_SIZE } from "../system/_style-chip.js";
6
+ import { LABEL_FACE } from "../system/_style-label-face.js";
7
+ import { ROW_DISABLED_OPACITY } from "../system/_style-row-disabled.js";
3
8
  import { overlayPopupTransitionClasses, overlayPositionerClasses, overlaySurfaceClasses } from "../overlays/_surface.js";
4
- import { OPTION_ROW } from "../system/_style-option.js";
9
+ import { LISTBOX_PAD, OPTION_HEIGHT, OPTION_LEADING, OPTION_PAD, OPTION_ROW, OPTION_SELECTED_GROUND, OPTION_SELECTED_HIGHLIGHT_GROUND, OPTION_SELECTED_POINTER_GROUND } from "../system/_style-option.js";
5
10
  //#region src/forms/_listbox.ts
6
11
  /**
7
12
  * The shared skin of every filterable list in this group — `Combobox`,
@@ -21,7 +26,7 @@ const listboxPositionerClasses = overlayPositionerClasses;
21
26
  * space the positioner reports so a long list scrolls instead of overflowing the
22
27
  * viewport.
23
28
  */
24
- const listboxPopupClasses = `${overlaySurfaceClasses} ${overlayPopupTransitionClasses} w-(--anchor-width) max-w-(--available-width) overflow-hidden py-(--cue-space-1) outline-none`;
29
+ const listboxPopupClasses = `${overlaySurfaceClasses} ${overlayPopupTransitionClasses} w-(--anchor-width) max-w-(--available-width) overflow-hidden ${LISTBOX_PAD} outline-none`;
25
30
  /** The scroll container inside the popup. */
26
31
  const listboxListClasses = "max-h-[min(var(--available-height),18rem)] overflow-y-auto overscroll-contain outline-none";
27
32
  /**
@@ -29,7 +34,7 @@ const listboxListClasses = "max-h-[min(var(--available-height),18rem)] overflow-
29
34
  * navigation and the pointer agree on which row is active, and the tint is
30
35
  * `accent-soft` rather than a solid fill (the luma defect ruling).
31
36
  */
32
- const listboxItemClasses = `flex h-control-sm cursor-default items-center gap-(--cue-space-2) px-(--cue-space-3) ${CONTROL_FACE} text-(length:--cue-text-ui) ${OPTION_ROW} outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-40`;
37
+ const listboxItemClasses = `flex ${OPTION_HEIGHT} cursor-default items-center gap-(--cue-space-2) ${OPTION_PAD} ${CONTROL_FACE} text-(length:--cue-text-ui) ${OPTION_LEADING} ${OPTION_ROW} ${OPTION_SELECTED_GROUND} ${OPTION_SELECTED_HIGHLIGHT_GROUND} ${OPTION_SELECTED_POINTER_GROUND} outline-none select-none data-[disabled]:pointer-events-none ${ROW_DISABLED_OPACITY}`;
33
38
  /** The "nothing matched" line: same rhythm as a row, but muted and unreachable. */
34
39
  const listboxEmptyClasses = `flex h-control-sm items-center px-(--cue-space-3) ${CONTROL_FACE} text-(length:--cue-text-ui) text-fg-subtle select-none`;
35
40
  /** The tick gutter, always reserved so labels never jog sideways. */
@@ -41,18 +46,18 @@ const listboxIndicatorClasses = "flex size-icon-sm shrink-0 items-center justify
41
46
  */
42
47
  const chipFieldClasses = "flex w-full cursor-text flex-wrap items-center gap-(--cue-space-1) py-(--cue-space-1)";
43
48
  /**
44
- * A value chip inside the field: the `h-chip` token and the tinted-neutral
45
- * colours of `chipVariants`, but *not* that recipe.
46
- *
47
- * `Chip` is uppercase and wide-tracked because it labels a *state* — `ONLINE`,
48
- * `FAULT`. A chip here holds user data (a truss name, a tag), and uppercasing
49
- * user data throws away information the user typed on purpose. Same shape, same
50
- * palette, ordinary casing.
49
+ * The typing input inside a chip field: one line tall, so a row of chips and
50
+ * the input fit the field's `min-h-control-*` and the field stands on the
51
+ * control ladder beside an `Input` of its size. It was `h-control-sm`, which
52
+ * with the row's padding made an `md` field 38px beside a 32px input, chips or
53
+ * none (P188.field: coss.com/ui's is 32px, 36px on a phone, like its inputs).
54
+ * A second row of chips still grows the field.
51
55
  */
52
- const valueChipClasses = "group/chip inline-flex h-chip max-w-full min-w-0 cursor-default items-center gap-(--cue-space-1) rounded-control border border-border bg-surface-2 py-0 pr-(--cue-space-1) pl-(--cue-space-2) font-mono text-(length:--cue-text-label) leading-none text-fg-muted outline-none select-none data-[highlighted]:border-accent/60 data-[highlighted]:text-fg focus-within:border-accent/60 focus-within:text-fg";
56
+ const chipInputClasses = "h-auto w-auto min-w-[6ch]";
57
+ const valueChipClasses = `group/chip inline-flex ${CHIP_HEIGHT} max-w-full min-w-0 cursor-default items-center gap-(--cue-space-1) ${CHIP_RADIUS} border border-[color:var(--cue-style-tag-edge,var(--cue-border))] bg-surface-2 py-0 pr-(--cue-space-1) pl-[var(--cue-style-tag-pad,var(--cue-space-2))] ${LABEL_FACE} ${CHIP_SIZE} leading-none ${CHIP_INK_NEUTRAL} outline-none select-none data-[highlighted]:border-accent/60 data-[highlighted]:text-fg focus-within:border-accent/60 focus-within:text-fg`;
53
58
  /** The chip's remove affordance. */
54
59
  const chipRemoveClasses = `flex size-icon-sm shrink-0 cursor-pointer items-center justify-center rounded-control border-0 bg-transparent p-0 text-fg-subtle outline-none transition-colors hover:text-fg ${FOCUS_RING}`;
55
60
  /** The trailing caret / clear affordance beside a filterable input. */
56
- const listboxAdornmentClasses = `flex shrink-0 cursor-pointer items-center justify-center rounded-control border-0 bg-transparent p-0 text-fg-subtle outline-none transition-colors hover:text-fg ${FOCUS_RING}`;
61
+ const listboxAdornmentClasses = `flex shrink-0 cursor-pointer items-center justify-center rounded-control border-0 bg-transparent p-0 ${GLYPH_INK_SUBTLE} ${GLYPH_OPACITY_SVG} outline-none transition-colors hover:text-fg ${FOCUS_RING}`;
57
62
  //#endregion
58
- export { chipFieldClasses, chipRemoveClasses, listboxAdornmentClasses, listboxEmptyClasses, listboxIndicatorClasses, listboxItemClasses, listboxListClasses, listboxPopupClasses, listboxPositionerClasses, valueChipClasses };
63
+ export { chipFieldClasses, chipInputClasses, chipRemoveClasses, listboxAdornmentClasses, listboxEmptyClasses, listboxIndicatorClasses, listboxItemClasses, listboxListClasses, listboxPopupClasses, listboxPositionerClasses, valueChipClasses };