@cueplusplus/ui 0.17.0 → 0.18.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 (203) hide show
  1. package/CHANGELOG.md +76 -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/date/_trigger.js +4 -1
  11. package/dist/date/calendar.js +15 -9
  12. package/dist/forms/_chassis.d.ts +10 -2
  13. package/dist/forms/_chassis.js +15 -5
  14. package/dist/forms/_listbox.js +18 -13
  15. package/dist/forms/checkbox.js +9 -6
  16. package/dist/forms/field.js +5 -5
  17. package/dist/forms/input-group.js +11 -2
  18. package/dist/forms/multi-select.js +4 -3
  19. package/dist/forms/number-field.js +6 -3
  20. package/dist/forms/otp-field.js +15 -6
  21. package/dist/forms/radio-group.js +7 -5
  22. package/dist/forms/select.js +8 -5
  23. package/dist/forms/slider.js +5 -3
  24. package/dist/forms/switch.js +6 -4
  25. package/dist/forms/tags-input.js +4 -3
  26. package/dist/forms/textarea.js +2 -1
  27. package/dist/forms/toggle-group.js +2 -1
  28. package/dist/forms/toggle.js +3 -1
  29. package/dist/instruments/meter.js +2 -1
  30. package/dist/instruments/progress.js +6 -3
  31. package/dist/instruments/stat.js +5 -3
  32. package/dist/instruments/table.js +3 -2
  33. package/dist/layout/_collapse.js +24 -8
  34. package/dist/layout/accordion.js +2 -1
  35. package/dist/layout/breadcrumb.js +8 -7
  36. package/dist/layout/card.js +2 -1
  37. package/dist/layout/collapsible.js +2 -1
  38. package/dist/layout/link.d.ts +14 -0
  39. package/dist/layout/link.js +4 -4
  40. package/dist/layout/pagination.js +7 -8
  41. package/dist/overlays/_surface.d.ts +4 -4
  42. package/dist/overlays/_surface.js +8 -7
  43. package/dist/overlays/alert-dialog.js +1 -1
  44. package/dist/overlays/command-palette.js +23 -8
  45. package/dist/overlays/dialog.js +1 -1
  46. package/dist/overlays/drawer.js +8 -1
  47. package/dist/overlays/hover-card.js +3 -1
  48. package/dist/overlays/popover.js +2 -1
  49. package/dist/overlays/toast.js +8 -4
  50. package/dist/overlays/tooltip.js +3 -4
  51. package/dist/primitives/avatar.js +6 -2
  52. package/dist/primitives/button.d.ts +1 -1
  53. package/dist/primitives/button.js +10 -7
  54. package/dist/primitives/chip.d.ts +0 -36
  55. package/dist/primitives/chip.js +14 -46
  56. package/dist/primitives/icon-button.d.ts +1 -1
  57. package/dist/primitives/kbd.js +2 -2
  58. package/dist/primitives/skeleton.js +2 -1
  59. package/dist/system/_style-accordion-rule.js +32 -0
  60. package/dist/system/_style-avatar.js +20 -0
  61. package/dist/system/_style-body-leading.js +1 -3
  62. package/dist/system/_style-body.js +7 -2
  63. package/dist/system/_style-caption-ink.js +17 -0
  64. package/dist/system/_style-caption-size.js +19 -0
  65. package/dist/system/_style-caption-weight.js +18 -0
  66. package/dist/system/_style-card-gap.js +14 -0
  67. package/dist/system/_style-cell.js +18 -0
  68. package/dist/system/_style-check-glyph.js +14 -0
  69. package/dist/system/_style-check.js +8 -1
  70. package/dist/system/_style-chip.js +41 -1
  71. package/dist/system/_style-choice-gap.js +15 -0
  72. package/dist/system/_style-collapse.js +81 -1
  73. package/dist/system/_style-control-gap.js +14 -0
  74. package/dist/system/_style-control-label.js +8 -1
  75. package/dist/system/_style-crumb.js +44 -0
  76. package/dist/system/_style-day.js +25 -0
  77. package/dist/system/_style-disabled.js +70 -0
  78. package/dist/system/_style-disclosure.js +21 -0
  79. package/dist/system/_style-empty-state.js +42 -0
  80. package/dist/system/_style-field-chassis.js +38 -0
  81. package/dist/system/_style-field-gap.js +12 -0
  82. package/dist/system/_style-glyph-ink.js +20 -0
  83. package/dist/system/_style-glyph-opacity.js +20 -0
  84. package/dist/system/_style-glyph-size.js +21 -0
  85. package/dist/system/_style-group-gap.js +15 -0
  86. package/dist/system/_style-group-label-pad.js +14 -0
  87. package/dist/system/_style-group-label.js +24 -0
  88. package/dist/system/_style-help.js +10 -1
  89. package/dist/system/_style-hover-card-width.js +15 -0
  90. package/dist/system/_style-kbd.js +13 -1
  91. package/dist/system/_style-link.js +15 -3
  92. package/dist/system/_style-menu.js +14 -1
  93. package/dist/system/_style-meter.js +15 -0
  94. package/dist/system/_style-nav-menu.js +48 -0
  95. package/dist/system/_style-option.js +61 -4
  96. package/dist/system/_style-otp.js +15 -0
  97. package/dist/system/_style-outline-hover.js +18 -0
  98. package/dist/system/_style-page.js +17 -0
  99. package/dist/system/_style-palette.js +18 -0
  100. package/dist/system/_style-panel.js +21 -0
  101. package/dist/system/_style-popover-width.js +15 -0
  102. package/dist/system/_style-radio.js +19 -0
  103. package/dist/system/_style-row-disabled.js +17 -0
  104. package/dist/system/_style-row.js +30 -0
  105. package/dist/system/_style-scrollbar.js +19 -0
  106. package/dist/system/_style-segment-pad.js +15 -0
  107. package/dist/system/_style-skeleton.js +15 -0
  108. package/dist/system/_style-slider.js +26 -0
  109. package/dist/system/_style-stat.js +31 -0
  110. package/dist/system/_style-stepper.js +16 -0
  111. package/dist/system/_style-switch.js +26 -0
  112. package/dist/system/_style-tab-hover.js +15 -0
  113. package/dist/system/_style-text-focus.js +26 -0
  114. package/dist/system/_style-toast.js +22 -0
  115. package/dist/system/_style-toggle.js +50 -0
  116. package/dist/system/_style-toolbar.js +23 -0
  117. package/dist/system/_style-tooltip.js +30 -1
  118. package/manifest/components/accordion.json +22 -1
  119. package/manifest/components/alert-dialog.json +7 -0
  120. package/manifest/components/app-bar.json +42 -0
  121. package/manifest/components/autocomplete.json +48 -1
  122. package/manifest/components/avatar-group.json +7 -0
  123. package/manifest/components/avatar.json +7 -0
  124. package/manifest/components/breadcrumb.json +7 -2
  125. package/manifest/components/button.json +16 -1
  126. package/manifest/components/calendar.json +6 -0
  127. package/manifest/components/card.json +1 -0
  128. package/manifest/components/channel-matrix.json +6 -0
  129. package/manifest/components/chart-tooltip-content.json +6 -0
  130. package/manifest/components/checkbox-group.json +22 -1
  131. package/manifest/components/checkbox.json +22 -1
  132. package/manifest/components/chip.json +6 -0
  133. package/manifest/components/collapsible.json +22 -0
  134. package/manifest/components/color-field.json +19 -0
  135. package/manifest/components/color-picker.json +19 -0
  136. package/manifest/components/combobox.json +48 -1
  137. package/manifest/components/command-palette.json +11 -0
  138. package/manifest/components/composer.json +19 -0
  139. package/manifest/components/context-menu.json +6 -0
  140. package/manifest/components/date-field.json +18 -0
  141. package/manifest/components/date-picker.json +22 -0
  142. package/manifest/components/date-range-picker.json +22 -0
  143. package/manifest/components/dialog.json +7 -0
  144. package/manifest/components/disclosure.json +22 -0
  145. package/manifest/components/dmx-bar.json +6 -0
  146. package/manifest/components/dmx-strip.json +6 -0
  147. package/manifest/components/drawer.json +7 -0
  148. package/manifest/components/dropdown-menu.json +6 -0
  149. package/manifest/components/empty-state.json +13 -0
  150. package/manifest/components/env-var-input.json +19 -0
  151. package/manifest/components/field-description.json +2 -1
  152. package/manifest/components/field-error.json +2 -1
  153. package/manifest/components/field-label.json +2 -1
  154. package/manifest/components/field.json +2 -1
  155. package/manifest/components/hover-card.json +8 -0
  156. package/manifest/components/input-group.json +21 -0
  157. package/manifest/components/input.json +19 -0
  158. package/manifest/components/kbd.json +2 -0
  159. package/manifest/components/link.json +23 -0
  160. package/manifest/components/menubar.json +6 -0
  161. package/manifest/components/meter.json +1 -0
  162. package/manifest/components/multi-select.json +49 -1
  163. package/manifest/components/musical-time-input.json +19 -0
  164. package/manifest/components/navigation-menu.json +16 -0
  165. package/manifest/components/number-field.json +21 -0
  166. package/manifest/components/otp-field.json +20 -0
  167. package/manifest/components/pagination.json +19 -0
  168. package/manifest/components/panel-header.json +3 -0
  169. package/manifest/components/panel.json +3 -0
  170. package/manifest/components/password-input.json +19 -0
  171. package/manifest/components/popover.json +7 -0
  172. package/manifest/components/progress.json +4 -0
  173. package/manifest/components/radio-group.json +6 -0
  174. package/manifest/components/radio.json +6 -0
  175. package/manifest/components/row.json +3 -0
  176. package/manifest/components/scroll-area.json +3 -1
  177. package/manifest/components/scrollable-tabs-list.json +3 -0
  178. package/manifest/components/scrub-input.json +19 -0
  179. package/manifest/components/seam-list.json +3 -0
  180. package/manifest/components/search-input.json +19 -0
  181. package/manifest/components/segmented-control.json +1 -0
  182. package/manifest/components/select.json +25 -0
  183. package/manifest/components/sheet.json +6 -0
  184. package/manifest/components/skeleton.json +2 -0
  185. package/manifest/components/slider.json +8 -0
  186. package/manifest/components/stat.json +8 -0
  187. package/manifest/components/switch.json +22 -0
  188. package/manifest/components/table-scroll-region.json +2 -0
  189. package/manifest/components/table.json +2 -0
  190. package/manifest/components/tabs.json +3 -0
  191. package/manifest/components/tags-input.json +49 -1
  192. package/manifest/components/textarea.json +19 -0
  193. package/manifest/components/theme-configurator.json +6 -0
  194. package/manifest/components/time-field.json +18 -0
  195. package/manifest/components/toast.json +9 -0
  196. package/manifest/components/toggle-group.json +2 -1
  197. package/manifest/components/toggle.json +28 -0
  198. package/manifest/components/toolbar.json +19 -0
  199. package/manifest/components/tooltip.json +11 -0
  200. package/manifest/fixtures.json +15 -0
  201. package/manifest/manifest.json +84 -84
  202. package/manifest/tokens.json +155 -1
  203. package/package.json +6 -6
@@ -0,0 +1,70 @@
1
+ //#region src/system/_style-disabled.ts
2
+ /**
3
+ * A disabled control's opacity, fill and ink (round 6, spec §11, lane R6.T:
4
+ * `style-disabled-opacity`, `style-disabled-fill`, `style-disabled-ink`).
5
+ *
6
+ * The chassis marks a disabled control by fading it to 40%, whatever the Look.
7
+ * stripe.com's system paints its disabled controls instead: a button, a
8
+ * checkbox, a switch's track and a text field fill with its quiet surface
9
+ * (`--hds-color-input-bg-disabled`, #e5edf5 over white), a disabled label and
10
+ * button text take a pale ink (`--hds-color-input-text-disabled`, #95a4ba),
11
+ * and nothing fades (T143, T132, T145, T146). So a set may lift the fade and
12
+ * name the fill and the ink.
13
+ *
14
+ * **Every reader falls back to what its control drew before**: the fade to
15
+ * `0.4`, each fill and ink to the resting value of the same control and
16
+ * state, spelled here byte for byte, so a disabled control under a set that
17
+ * declines all three is exactly the faded control it was. Each is spelled
18
+ * out whole, because Tailwind reads class names from source text and cannot
19
+ * see one built at run time.
20
+ *
21
+ * **Its own module**, because docgen credits every `--cue-*` in a module to
22
+ * each component that imports it: the button chassis, the field chassis, the
23
+ * checkbox and the switch each import the constants they spend.
24
+ *
25
+ * @internal Not part of the public API.
26
+ */
27
+ /** The fade on `:disabled` (a native control). */
28
+ const DISABLED_OPACITY = "disabled:opacity-[var(--cue-style-disabled-opacity,0.4)]";
29
+ /** The fade on `[data-disabled]` (Base UI's own attribute). */
30
+ const DATA_DISABLED_OPACITY = "data-[disabled]:opacity-[var(--cue-style-disabled-opacity,0.4)]";
31
+ /** The fade on a control's label, which holds the disabled control. */
32
+ const LABEL_DISABLED_OPACITY = "has-[[data-disabled]]:opacity-[var(--cue-style-disabled-opacity,0.4)]";
33
+ /** A disabled control label's ink, falling back to the label ink it drew (`LABEL_INK`). */
34
+ const LABEL_DISABLED_INK = "has-[[data-disabled]]:text-[color:var(--cue-style-disabled-ink,var(--cue-style-label-ink,var(--cue-fg-muted)))]";
35
+ /**
36
+ * The field chassis's fill when disabled: its own two layers (`STROKE_SUNKEN`),
37
+ * with the fill layer's `sunken` read through `style-disabled-fill`, on
38
+ * `:disabled` and on `[data-disabled]`.
39
+ */
40
+ const FIELD_DISABLED_FILL = "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)))]";
41
+ /**
42
+ * The button tones' fill and ink when disabled, each falling back to the tone's own resting fill and ink.
43
+ * The two transparent tones keep their ground and take an edge instead (`style-disabled-edge`, falling
44
+ * back to the edge each drew): stripe.com's disabled icon button stays on its ground and draws a 1px rim
45
+ * in its disabled border ink (T139), where its filled buttons fill (T143).
46
+ */
47
+ const DISABLED_TONES = {
48
+ primary: "disabled:bg-[color:var(--cue-style-disabled-fill,var(--cue-accent-fill))] disabled:text-[color:var(--cue-style-disabled-ink,var(--cue-accent-fill-fg))]",
49
+ secondary: "disabled:bg-[color:var(--cue-style-disabled-fill,var(--cue-style-secondary-ground,var(--cue-surface-2)))] disabled:text-[color:var(--cue-style-disabled-ink,var(--cue-style-secondary-ink,var(--cue-fg-muted)))]",
50
+ ghost: "disabled:border-[color:var(--cue-style-disabled-edge,transparent)] disabled:text-[color:var(--cue-style-disabled-ink,var(--cue-style-quiet-ink,var(--cue-fg-muted)))]",
51
+ outline: "disabled:border-[color:var(--cue-style-disabled-edge,var(--cue-style-outline-edge,var(--cue-border)))] disabled:text-[color:var(--cue-style-disabled-ink,var(--cue-style-quiet-ink,var(--cue-fg)))]",
52
+ danger: "disabled:bg-[color:var(--cue-style-disabled-fill,var(--cue-danger))] disabled:text-[color:var(--cue-style-disabled-ink,var(--cue-danger-fg))]",
53
+ "danger-outline": "disabled:bg-[color:var(--cue-style-disabled-fill,transparent)] disabled:text-[color:var(--cue-style-disabled-ink,var(--cue-danger))]"
54
+ };
55
+ /**
56
+ * The checkbox's box when disabled: its fill, and its edge, which a disabled
57
+ * box draws in its own fill (the source's disabled box draws no border, so
58
+ * the two read as one square). Each state keeps its own fallback: the
59
+ * resting `sunken` and edge, and the checked and indeterminate `accent`.
60
+ *
61
+ * The checked and indeterminate edges skip an invalid box: they name two
62
+ * attributes and so outrank `data-[invalid]:border-danger`, and a disabled,
63
+ * checked, invalid box drew `danger` before round 6 (the closing pass's
64
+ * adversarial review).
65
+ */
66
+ const CHECK_DISABLED = "data-[disabled]:bg-[color:var(--cue-style-disabled-fill,var(--cue-sunken))] data-[disabled]:border-[color:var(--cue-style-disabled-fill,var(--cue-style-check-edge,var(--cue-border)))] data-[disabled]:data-[checked]:bg-[color:var(--cue-style-disabled-fill,var(--cue-accent))] data-[disabled]:data-[checked]:not-data-[invalid]:border-[color:var(--cue-style-disabled-fill,var(--cue-accent))] data-[disabled]:data-[indeterminate]:bg-[color:var(--cue-style-disabled-fill,var(--cue-accent))] data-[disabled]:data-[indeterminate]:not-data-[invalid]:border-[color:var(--cue-style-disabled-fill,var(--cue-accent))]";
67
+ /** The switch's track when disabled, unchecked and checked, each state keeping its own fallback. */
68
+ const SWITCH_DISABLED_TRACK = "data-[disabled]:bg-[color:var(--cue-style-disabled-fill,var(--cue-surface-3))] data-[disabled]:data-[checked]:bg-[color:var(--cue-style-disabled-fill,var(--cue-accent))]";
69
+ //#endregion
70
+ export { CHECK_DISABLED, DATA_DISABLED_OPACITY, DISABLED_OPACITY, DISABLED_TONES, FIELD_DISABLED_FILL, LABEL_DISABLED_INK, LABEL_DISABLED_OPACITY, SWITCH_DISABLED_TRACK };
@@ -0,0 +1,21 @@
1
+ //#region src/system/_style-disclosure.ts
2
+ /**
3
+ * The inline disclosure toggle's ink, hover ink and weight (round 6, spec §11,
4
+ * lane R6.Z: `style-disclosure-ink`, `style-disclosure-hover-ink`,
5
+ * `style-disclosure-weight`), each falling back to what `Disclosure` drew:
6
+ * `fg-subtle`, `fg-muted` under the pointer, and the weight it inherited.
7
+ * greptile.com's phone contents box is a `details` whose summary is 500 in
8
+ * `fg` and stays so under the pointer (Z137).
9
+ *
10
+ * **Optional** (spec §3.0). Its own module for docgen's reason: the accordion
11
+ * and collapsible triggers ride `_style-collapse.ts` and read none of these.
12
+ *
13
+ * @internal Not part of the public API.
14
+ */
15
+ const DISCLOSURE_INK = "text-[color:var(--cue-style-disclosure-ink,var(--cue-fg-subtle))]";
16
+ /** @see DISCLOSURE_INK */
17
+ const DISCLOSURE_HOVER_INK = "hover:text-[color:var(--cue-style-disclosure-hover-ink,var(--cue-fg-muted))]";
18
+ /** @see DISCLOSURE_INK */
19
+ const DISCLOSURE_WEIGHT = "font-[number:var(--cue-style-disclosure-weight,inherit)]";
20
+ //#endregion
21
+ export { DISCLOSURE_HOVER_INK, DISCLOSURE_INK, DISCLOSURE_WEIGHT };
@@ -0,0 +1,42 @@
1
+ //#region src/system/_style-empty-state.ts
2
+ /**
3
+ * The empty state's own voice (round 6, spec §11, lane R6.P): its title's face,
4
+ * size, weight and leading (`style-empty-title-face`, `-size`, `-weight`,
5
+ * `-leading`), falling back to the inherited face, the `text-emphasis` rung and
6
+ * the inherited weight and leading; its icon's size (`style-empty-icon-size`),
7
+ * falling back to `space-7`; the gap between its parts (`style-empty-gap`),
8
+ * falling back to `space-3`; and its block padding (`style-empty-pad`), falling
9
+ * back to `space-7`. coss.com/ui's Empty sets a 20px, 600-weight heading-face
10
+ * title on a 1.4 line, an 18px icon, 24px between its parts and 80px (48px on a
11
+ * phone) above and below (P156).
12
+ *
13
+ * **Optional** (spec §3.0): each name is declared by `porcelain` alone and each
14
+ * reader falls back to what the component drew. Its own module for docgen's
15
+ * reason: one component's tokens per file.
16
+ *
17
+ * @internal Not part of the public API.
18
+ */
19
+ const EMPTY_TITLE_FACE = "font-[family-name:var(--cue-style-empty-title-face,inherit)]";
20
+ /**
21
+ * The hint's face and weight: the body names (`style-body-face`,
22
+ * `style-body-weight`), each falling back to the `inherit` the hint drew — it
23
+ * set neither, so a caller's face on the root reached it. The shared
24
+ * `BODY_VOICE` falls back to mono, which is what the sites it replaced drew; the
25
+ * title's face above falls back to `inherit` for the same reason (the closing
26
+ * pass's adversarial review).
27
+ */
28
+ const EMPTY_HINT_VOICE = "font-[family-name:var(--cue-style-body-face,inherit)] font-[number:var(--cue-style-body-weight,inherit)]";
29
+ /** @see EMPTY_TITLE_FACE */
30
+ const EMPTY_TITLE_SIZE = "text-[length:var(--cue-style-empty-title-size,var(--cue-text-emphasis))]";
31
+ /** @see EMPTY_TITLE_FACE */
32
+ const EMPTY_TITLE_WEIGHT = "font-[number:var(--cue-style-empty-title-weight,inherit)]";
33
+ /** @see EMPTY_TITLE_FACE */
34
+ const EMPTY_TITLE_LEADING = "leading-[var(--cue-style-empty-title-leading,inherit)]";
35
+ /** @see EMPTY_TITLE_FACE */
36
+ const EMPTY_ICON_SIZE = "size-[var(--cue-style-empty-icon-size,var(--cue-space-7))]";
37
+ /** @see EMPTY_TITLE_FACE */
38
+ const EMPTY_GAP = "gap-[var(--cue-style-empty-gap,var(--cue-space-3))]";
39
+ /** @see EMPTY_TITLE_FACE */
40
+ const EMPTY_PAD = "py-[var(--cue-style-empty-pad,var(--cue-space-7))]";
41
+ //#endregion
42
+ export { EMPTY_GAP, EMPTY_HINT_VOICE, EMPTY_ICON_SIZE, EMPTY_PAD, EMPTY_TITLE_FACE, EMPTY_TITLE_LEADING, EMPTY_TITLE_SIZE, EMPTY_TITLE_WEIGHT };
@@ -0,0 +1,38 @@
1
+ //#region src/system/_style-field-chassis.ts
2
+ /**
3
+ * The field chassis's inline padding and hover edge (round 6, spec §11, lane
4
+ * R6.T: `style-field-pad`, `style-field-hover-edge`), and its invalid edge.
5
+ *
6
+ * stripe.com pads its text field, textarea and select trigger 16px
7
+ * (`--hds-space-core-200`) where ours pad 12px (`space-4` at normal), so the
8
+ * padding is the rung times a set's multiplier (T132, T148); it draws a
9
+ * lavender edge under the pointer (`--hds-color-input-border-hoverSubdued`,
10
+ * T132, T148, T153). An invalid field's resting edge there is a pale red
11
+ * (`--hds-color-input-border-errorBlur`, T147), which Tender refuses (spec
12
+ * §6.2), so no set spends a name for it and the edge is plain `danger`.
13
+ *
14
+ * **The fallbacks are the classes they replace**: each rung's `px-(--cue-space-*)`
15
+ * times 1, the `transparent` the chassis's border already is (so a pointer
16
+ * over a field under a set that declines the name changes nothing: Tailwind
17
+ * emits `hover:` before `focus:` and `data-[invalid]:`, so a focused or
18
+ * invalid field keeps its own edge).
19
+ *
20
+ * @internal Not part of the public API.
21
+ */
22
+ const FIELD_PAD_SM = "px-[calc(var(--cue-space-3)*var(--cue-style-field-pad,1))]";
23
+ /** The `md` rung's inline padding, and the textarea's. */
24
+ const FIELD_PAD_MD = "px-[calc(var(--cue-space-4)*var(--cue-style-field-pad,1))]";
25
+ /** The `lg` rung's inline padding. */
26
+ const FIELD_PAD_LG = "px-[calc(var(--cue-space-5)*var(--cue-style-field-pad,1))]";
27
+ /** The edge under a pointer that can hover. */
28
+ const FIELD_HOVER_EDGE = "hover:border-[color:var(--cue-style-field-hover-edge,transparent)]";
29
+ /** An invalid field's edge: `danger`, the class the chassis drew before round 6. */
30
+ const INVALID_EDGE = "data-[invalid]:border-danger";
31
+ /**
32
+ * The select trigger's own hover edge: it draws `border-strong` under the
33
+ * pointer where the rest of the chassis draws nothing, so its reader falls
34
+ * back to that, and a set's field hover edge reaches it too.
35
+ */
36
+ const SELECT_HOVER_EDGE = "hover:not-data-disabled:border-[color:var(--cue-style-field-hover-edge,var(--cue-border-strong))]";
37
+ //#endregion
38
+ export { FIELD_HOVER_EDGE, FIELD_PAD_LG, FIELD_PAD_MD, FIELD_PAD_SM, INVALID_EDGE, SELECT_HOVER_EDGE };
@@ -0,0 +1,12 @@
1
+ //#region src/system/_style-field-gap.ts
2
+ /**
3
+ * The gap between a field's label, its control and its help line (round 6,
4
+ * spec §11, lane R6.T: `style-field-gap`, MULT), falling back to the `space-2`
5
+ * it drew times 1. stripe.com leaves 8px under a label
6
+ * (`.hds-field__label-layout`'s margin) where ours leaves 6px at normal (T147).
7
+ *
8
+ * @internal Not part of the public API.
9
+ */
10
+ const FIELD_GAP = "gap-[calc(var(--cue-space-2)*var(--cue-style-field-gap,1))]";
11
+ //#endregion
12
+ export { FIELD_GAP };
@@ -0,0 +1,20 @@
1
+ //#region src/system/_style-glyph-ink.ts
2
+ /**
3
+ * A control's glyph ink (round 6, spec §11, lane R6.P: `style-glyph-ink`): the
4
+ * chevron on a select and a filterable field, a number field's steppers, the
5
+ * date trigger's calendar mark, a calendar's month arrows, pagination's
6
+ * ellipsis and an empty state's icon. Each falls back to the `fg-subtle` or
7
+ * `fg-muted` it drew. coss.com/ui draws all of them in `fg` (P151.chevron-ink,
8
+ * P174.chevron-ink, P165.stepper-ink, P167.ellipsis, P189.nav-ink,
9
+ * P156.icon-ink).
10
+ *
11
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
12
+ * file, so only the components that read it are credited with it.
13
+ *
14
+ * @internal Not part of the public API.
15
+ */
16
+ const GLYPH_INK_SUBTLE = "text-[color:var(--cue-style-glyph-ink,var(--cue-fg-subtle))]";
17
+ /** @see GLYPH_INK_SUBTLE */
18
+ const GLYPH_INK_MUTED = "text-[color:var(--cue-style-glyph-ink,var(--cue-fg-muted))]";
19
+ //#endregion
20
+ export { GLYPH_INK_MUTED, GLYPH_INK_SUBTLE };
@@ -0,0 +1,20 @@
1
+ //#region src/system/_style-glyph-opacity.ts
2
+ /**
3
+ * An affordance glyph's opacity (round 6, spec §11, lane R6.P:
4
+ * `style-glyph-opacity`): the chevron on a select and a filterable field, the
5
+ * date trigger's calendar mark, a calendar's month arrows, and a glyph in an
6
+ * input group's gutters. Each falls back to `1`, the opacity it drew.
7
+ * coss.com/ui paints all of them in `fg` at 80% (P151, P153, P161, P174,
8
+ * P189), and its number-field steppers, pagination ellipsis and empty-state
9
+ * icon at full strength, so those read `style-glyph-ink` alone.
10
+ *
11
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
12
+ * file, so only the components that read it are credited with it.
13
+ *
14
+ * @internal Not part of the public API.
15
+ */
16
+ const GLYPH_OPACITY = "opacity-[var(--cue-style-glyph-opacity,1)]";
17
+ /** @see GLYPH_OPACITY — on the glyphs inside a wrapper, so a focus ring on the wrapper keeps its strength. */
18
+ const GLYPH_OPACITY_SVG = "[&_svg]:opacity-[var(--cue-style-glyph-opacity,1)]";
19
+ //#endregion
20
+ export { GLYPH_OPACITY, GLYPH_OPACITY_SVG };
@@ -0,0 +1,21 @@
1
+ //#region src/system/_style-glyph-size.ts
2
+ /**
3
+ * A control's glyph size (round 6, spec §11, lane R6.P: `style-glyph-size`): the
4
+ * date trigger's calendar mark and a number field's stepper glyphs, falling
5
+ * back to the `icon-sm` they drew. coss.com/ui draws both 16px (P153.icon,
6
+ * P165.stepper-glyph).
7
+ *
8
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
9
+ * file, so only the components that read it are credited with it.
10
+ *
11
+ * @internal Not part of the public API.
12
+ */
13
+ const GLYPH_SIZE = "size-[var(--cue-style-glyph-size,var(--cue-icon-sm))]";
14
+ /**
15
+ * The same size for a glyph set as type: a number field's − and +, which fall
16
+ * back to the size they inherited. coss.com/ui's stepper glyphs are 16px
17
+ * (P165.stepper-glyph).
18
+ */
19
+ const GLYPH_TEXT_SIZE = "text-[length:var(--cue-style-glyph-size,inherit)]";
20
+ //#endregion
21
+ export { GLYPH_SIZE, GLYPH_TEXT_SIZE };
@@ -0,0 +1,15 @@
1
+ //#region src/system/_style-group-gap.ts
2
+ /**
3
+ * The gap between the items of a group control (round 6, spec §11, lane R6.P:
4
+ * `style-group-gap`): a ToggleGroup's toggles and a tab list's tabs, falling
5
+ * back to the `space-1` both drew. coss.com/ui sets both 2px apart (P141,
6
+ * P182.gap).
7
+ *
8
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
9
+ * file, so only the components that read it are credited with it.
10
+ *
11
+ * @internal Not part of the public API.
12
+ */
13
+ const GROUP_GAP = "gap-[var(--cue-style-group-gap,var(--cue-space-1))]";
14
+ //#endregion
15
+ export { GROUP_GAP };
@@ -0,0 +1,14 @@
1
+ //#region src/system/_style-group-label-pad.ts
2
+ /**
3
+ * A menu group label's block padding (round 6, spec §11, lane R6.P:
4
+ * `style-group-label-pad`), falling back to the `0px` it drew inside its fixed
5
+ * row height. coss.com/ui pads its labels 6px (P163.label-pad).
6
+ *
7
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
8
+ * file, so only the components that read it are credited with it.
9
+ *
10
+ * @internal Not part of the public API.
11
+ */
12
+ const GROUP_LABEL_PAD = "py-[var(--cue-style-group-label-pad,0px)]";
13
+ //#endregion
14
+ export { GROUP_LABEL_PAD };
@@ -0,0 +1,24 @@
1
+ //#region src/system/_style-group-label.ts
2
+ /**
3
+ * A caption over a group of rows (round 6, spec §11, lane R6.P:
4
+ * `style-group-label-size`, `style-group-label-ink`): a menu's and a command
5
+ * palette's group labels. A menu's falls back through `style-label-size` and
6
+ * `style-label-ink` to the rung and ink it drew; the palette's, which read no
7
+ * label name, to its `text-micro` and `fg-subtle`. coss.com/ui sets both at
8
+ * 12px in `fg-muted` (P163.label-size, P152.group-label, P152.group-label-ink),
9
+ * where its field labels are 14px `fg`.
10
+ *
11
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
12
+ * file, so only the components that read it are credited with it.
13
+ *
14
+ * @internal Not part of the public API.
15
+ */
16
+ const GROUP_LABEL_SIZE = "text-[length:var(--cue-style-group-label-size,var(--cue-style-label-size,var(--cue-text-label)))]";
17
+ /** @see GROUP_LABEL_SIZE */
18
+ const GROUP_LABEL_INK = "text-[color:var(--cue-style-group-label-ink,var(--cue-style-label-ink,var(--cue-fg-subtle)))]";
19
+ /** @see GROUP_LABEL_SIZE — the palette's, which read no label name. */
20
+ const GROUP_LABEL_SIZE_MICRO = "text-[length:var(--cue-style-group-label-size,var(--cue-text-micro))]";
21
+ /** @see GROUP_LABEL_SIZE */
22
+ const GROUP_LABEL_INK_SUBTLE = "text-[color:var(--cue-style-group-label-ink,var(--cue-fg-subtle))]";
23
+ //#endregion
24
+ export { GROUP_LABEL_INK, GROUP_LABEL_INK_SUBTLE, GROUP_LABEL_SIZE, GROUP_LABEL_SIZE_MICRO };
@@ -25,5 +25,14 @@
25
25
  const HELP_SIZE = "text-[length:var(--cue-style-help-size,var(--cue-text-micro))]";
26
26
  /** @see HELP_SIZE — the description's ink; `FieldError` keeps `text-danger`. */
27
27
  const HELP_INK = "text-[color:var(--cue-style-help-ink,var(--cue-fg-subtle))]";
28
+ /**
29
+ * The help line's leading (round 6, spec §11, lane R6.T: `style-help-leading`),
30
+ * falling back to the body leading `FieldDescription` read. stripe.com sets
31
+ * its field description and its field error on one line height
32
+ * (`--hds-font-input-description-lineHeight`, 18.2px on 14px: 1.3, T147).
33
+ */
34
+ const HELP_LEADING = "leading-[var(--cue-style-help-leading,var(--cue-style-body-leading,inherit))]";
35
+ /** The error line's leading: the same name, falling back to the `inherit` `FieldError` drew (no leading class). */
36
+ const HELP_LEADING_ERROR = "leading-[var(--cue-style-help-leading,inherit)]";
28
37
  //#endregion
29
- export { HELP_INK, HELP_SIZE };
38
+ export { HELP_INK, HELP_LEADING, HELP_LEADING_ERROR, HELP_SIZE };
@@ -0,0 +1,15 @@
1
+ //#region src/system/_style-hover-card-width.ts
2
+ /**
3
+ * A hover card's width (round 6, spec §11, lane R6.P: `style-hover-card-width`),
4
+ * falling back to the 20rem it drew, under the same viewport cap. coss.com/ui's
5
+ * preview card is 256px (`w-64`, P169.width).
6
+ *
7
+ * **Optional** (spec §3.0): declared by `porcelain` alone, and the reader falls
8
+ * back to what the component drew. Its own module for docgen's reason: one
9
+ * component's tokens per file.
10
+ *
11
+ * @internal Not part of the public API.
12
+ */
13
+ const HOVER_CARD_WIDTH = "w-[min(var(--cue-style-hover-card-width,20rem),calc(100vw-2rem))]";
14
+ //#endregion
15
+ export { HOVER_CARD_WIDTH };
@@ -42,5 +42,17 @@ const KBD_SIZE = "text-[length:var(--cue-style-kbd-size,var(--cue-style-chip-siz
42
42
  * Look that names only the chip's keeps its key caps beside it.
43
43
  */
44
44
  const KBD_BOX = "h-[var(--cue-style-kbd-height,var(--cue-chip-h))] min-w-[var(--cue-style-kbd-height,var(--cue-chip-h))] px-[var(--cue-style-kbd-pad,var(--cue-space-2))] rounded-[var(--cue-style-kbd-radius,calc(var(--cue-radius-control)*var(--cue-radius-scale)))]";
45
+ /**
46
+ * A key's leading (round 6, spec §11, lane R6.P: `style-kbd-leading`), falling
47
+ * back to the `leading-none` it drew. coss.com/ui's keys set 12px on a 16px line
48
+ * (P162.leading).
49
+ */
50
+ const KBD_LEADING = "leading-[var(--cue-style-kbd-leading,1)]";
51
+ /**
52
+ * A key's fill (round 6, spec §11, lane R6.G: `style-kbd-fill`), falling back
53
+ * to the `surface-2` it drew. agent-native.com's header key sits on
54
+ * `bg-elevated`, #f4f3ef in light and #2e2e2e in dark (G141.fill).
55
+ */
56
+ const KBD_FILL = "bg-[color:var(--cue-style-kbd-fill,var(--cue-surface-2))]";
45
57
  //#endregion
46
- export { KBD_BOX, KBD_EDGE, KBD_SIZE };
58
+ export { KBD_BOX, KBD_EDGE, KBD_FILL, KBD_LEADING, KBD_SIZE };
@@ -40,7 +40,19 @@ const LINK_OFFSET = "underline-offset-[var(--cue-style-link-offset,4px)]";
40
40
  * `CONTROL_WEIGHT` says why.
41
41
  */
42
42
  const LINK_WEIGHT = "font-[number:var(--cue-style-link-weight,inherit)]";
43
- /** Every link's hover ink: the accent, or the set's `style-hover-ink`. */
44
- const HOVER_INK = "hover:text-[color:var(--cue-style-hover-ink,var(--cue-accent))]";
43
+ /**
44
+ * Every link's hover ink: the set's `style-link-hover-ink`, else its
45
+ * `style-hover-ink`, else the accent.
46
+ *
47
+ * Round 6 (spec §11, lane R6.T) splits the link's hover from the header
48
+ * nav's: `style-hover-ink` also colours `AppBar.Link` under the pointer, and
49
+ * stripe.com draws the two apart (its links hover to its brand-800, #2e2b8c;
50
+ * its nav's triggers stay in their solid ink, #061b31, T144, T151). So the
51
+ * link reads a name of its own first, falling back to the shared one, and a
52
+ * set that names neither renders exactly what it did.
53
+ */
54
+ const HOVER_INK = "hover:text-[color:var(--cue-style-link-hover-ink,var(--cue-style-hover-ink,var(--cue-accent)))]";
55
+ /** An underlined link's rule under the pointer: the same chain as {@link HOVER_INK}. */
56
+ const HOVER_RULE = "hover:decoration-[color:var(--cue-style-link-hover-ink,var(--cue-style-hover-ink,var(--cue-accent)))]";
45
57
  //#endregion
46
- export { HOVER_INK, INLINE_LINK_INK, LINK_INK, LINK_OFFSET, LINK_RULE, LINK_WEIGHT };
58
+ export { HOVER_INK, HOVER_RULE, INLINE_LINK_INK, LINK_INK, LINK_OFFSET, LINK_RULE, LINK_WEIGHT };
@@ -26,5 +26,18 @@ const MENU_ITEM_INK = "text-[color:var(--cue-style-quiet-ink,var(--cue-fg-muted)
26
26
  * they drew no corner.
27
27
  */
28
28
  const MENU_ITEM_RADIUS = "rounded-[var(--cue-style-menu-item-radius,calc(var(--cue-radius-control)*var(--cue-radius-scale)))]";
29
+ /**
30
+ * A menu popup's minimum width (round 6, spec §11, lane R6.P:
31
+ * `style-menu-min-width`), falling back to the `10rem` it drew. coss.com/ui's
32
+ * menus start at 8rem (`min-w-32`, P163.min-width).
33
+ */
34
+ const MENU_MIN_WIDTH = "min-w-[var(--cue-style-menu-min-width,10rem)]";
35
+ /**
36
+ * The inline inset of the rule between a menu's groups (round 6, spec §11, lane
37
+ * R6.P: `style-menu-separator-inset`), falling back to the `0px` it drew: the
38
+ * rule ran rim to rim. coss.com/ui's stops 8px short of each side
39
+ * (P163.separator-inset).
40
+ */
41
+ const MENU_SEPARATOR_INSET = "mx-[var(--cue-style-menu-separator-inset,0px)]";
29
42
  //#endregion
30
- export { MENU_ITEM_INK, MENU_ITEM_RADIUS };
43
+ export { MENU_ITEM_INK, MENU_ITEM_RADIUS, MENU_MIN_WIDTH, MENU_SEPARATOR_INSET };
@@ -0,0 +1,15 @@
1
+ //#region src/system/_style-meter.ts
2
+ /**
3
+ * A meter track's corner (round 6, spec §11, lane R6.P: `style-meter-radius`),
4
+ * falling back to the `rounded-full` it drew. coss.com/ui's meter track is
5
+ * square (P164.radius).
6
+ *
7
+ * **Optional** (spec §3.0): each name is declared by `porcelain` alone and each
8
+ * reader falls back to what the component drew. Its own module for docgen's
9
+ * reason: one component's tokens per file.
10
+ *
11
+ * @internal Not part of the public API.
12
+ */
13
+ const METER_RADIUS = "rounded-[var(--cue-style-meter-radius,calc(infinity*1px))]";
14
+ //#endregion
15
+ export { METER_RADIUS };
@@ -0,0 +1,48 @@
1
+ //#region src/system/_style-nav-menu.ts
2
+ /**
3
+ * `NavigationMenu`'s trigger (round 6, spec §11, lane R6.T): the header nav's
4
+ * voice, padding and resting ink, and two names of its own, `style-nav-height`
5
+ * and `style-nav-open-ground`.
6
+ *
7
+ * **It reads the header nav's names**, because a site's header draws its menu
8
+ * triggers and its plain links as one row, in one voice: stripe.com's four
9
+ * triggers and its Pricing link are all 14px, 400, #061b31 with no inline
10
+ * padding (T16, T151); replit.com's are 13.3px and 14px, one ink, one
11
+ * padding; greptile.com, coss.com and agent-native.com draw no header menu
12
+ * trigger, only links (probed 2026-09-28). So the trigger reads
13
+ * `style-nav-face`, `-case`, `-tracking`, `-size`, `-weight` and `-pad`,
14
+ * which `AppBar.Link` reads, and `style-quiet-ink`, `AppBar.Link`'s muted
15
+ * register. Each falls back to what the trigger drew — the control face, its
16
+ * own `text-ui`, an inherited weight, tracking and case, `0 space-3` and
17
+ * `fg-muted` — so a set that names none of them renders the trigger it did.
18
+ *
19
+ * The height and the open ground are its own: stripe.com's triggers stand
20
+ * 40px on the nav's own padding (ours ride the `md` control rung) and draw no
21
+ * ground when their panel is open (ours tint it `accent-soft`), T151.
22
+ *
23
+ * @internal Not part of the public API.
24
+ */
25
+ const NAV_TRIGGER_VOICE = "font-[family-name:var(--cue-style-nav-face,var(--cue-style-control-face,var(--cue-font-mono)))] [text-transform:var(--cue-style-nav-case,inherit)] tracking-[var(--cue-style-nav-tracking,inherit)] text-[length:var(--cue-style-nav-size,var(--cue-text-ui))] font-[number:var(--cue-style-nav-weight,inherit)]";
26
+ /** The trigger's resting ink: the header nav's muted register. */
27
+ const NAV_TRIGGER_INK = "text-[color:var(--cue-style-quiet-ink,var(--cue-fg-muted))]";
28
+ /** The trigger's padding: the header nav's. */
29
+ const NAV_TRIGGER_PAD = "p-[var(--cue-style-nav-pad,0_var(--cue-space-3))]";
30
+ /** The trigger's height. */
31
+ const NAV_TRIGGER_HEIGHT = "h-[var(--cue-style-nav-height,var(--cue-control-md))]";
32
+ /** An open trigger's ground. */
33
+ const NAV_OPEN_GROUND = "data-[popup-open]:bg-[color:var(--cue-style-nav-open-ground,var(--cue-accent-soft))]";
34
+ /**
35
+ * The caret's ink (round 6, spec §11, lane R6.K: `style-nav-caret-ink`),
36
+ * falling back to the `fg-subtle` it drew. replit.com draws its menu
37
+ * triggers' carets in the trigger's own ink, #37383c (K159).
38
+ */
39
+ const NAV_CARET_INK = "text-[color:var(--cue-style-nav-caret-ink,var(--cue-fg-subtle))]";
40
+ /**
41
+ * The trigger's hover ink: the header nav's `style-hover-ink`, falling back to
42
+ * the `fg` it hovered to. replit.com's triggers hover to #2c2e31, the same
43
+ * ink its header links hover to (K51, K159), so the trigger reads the name
44
+ * `AppBar.Link` reads rather than a fixed `fg`.
45
+ */
46
+ const NAV_TRIGGER_HOVER_INK = "hover:text-[color:var(--cue-style-hover-ink,var(--cue-fg))]";
47
+ //#endregion
48
+ export { NAV_CARET_INK, NAV_OPEN_GROUND, NAV_TRIGGER_HEIGHT, NAV_TRIGGER_HOVER_INK, NAV_TRIGGER_INK, NAV_TRIGGER_PAD, NAV_TRIGGER_VOICE };
@@ -29,14 +29,71 @@
29
29
  * selected row keeps the 400 it inherits, and a caller's `font-*` class on a
30
30
  * row still beats both, as it beat nothing before.
31
31
  *
32
- * `data-[highlighted]:text-fg` stays a class: every Look's highlighted row is
33
- * `fg`. The weight is spelt out whole rather than composed from
32
+ * The highlighted row's ink reads `style-option-highlight-ink` (round 6, lane
33
+ * R6.G), falling back to the `fg` every Look's highlighted row drew:
34
+ * agent-native.com's language listbox keeps its rows' `#3d3d3d` under the
35
+ * pointer (G143.hover-ink). The weight is spelt out whole rather than composed from
34
36
  * `_style-body-weight.ts`: a variant prefixed onto an interpolated constant is
35
37
  * a class that appears in no source file, and a consumer's Tailwind, which
36
38
  * scans this package's build for candidates, would never generate it.
37
39
  *
38
40
  * @internal Not part of the public API.
39
41
  */
40
- const OPTION_ROW = "rounded-[var(--cue-style-menu-item-radius,0px)] text-[color:var(--cue-style-option-ink,var(--cue-fg-muted))] [:where(&:not([data-selected]))]:font-[number:var(--cue-style-body-weight,inherit)] data-[highlighted]:bg-[color:var(--cue-style-menu-highlight,var(--cue-accent-soft))] data-[highlighted]:text-fg data-[selected]:text-[color:var(--cue-style-option-selected-ink,var(--cue-accent))]";
42
+ const OPTION_ROW = "rounded-[var(--cue-style-menu-item-radius,0px)] text-[color:var(--cue-style-option-ink,var(--cue-fg-muted))] [:where(&:not([data-selected]))]:font-[number:var(--cue-style-body-weight,inherit)] data-[highlighted]:bg-[color:var(--cue-style-menu-highlight,var(--cue-accent-soft))] data-[highlighted]:text-[color:var(--cue-style-option-highlight-ink,var(--cue-fg))] data-[selected]:text-[color:var(--cue-style-option-selected-ink,var(--cue-accent))]";
43
+ /**
44
+ * A listbox row's box (round 6, spec §11, lane R6.T: `style-option-pad`,
45
+ * `style-option-leading`, `style-option-height`): the select's rows and the
46
+ * combobox, autocomplete and multi-select rows (`forms/_listbox.ts`).
47
+ *
48
+ * stripe.com's rows (`.hds-listbox__item`) pad 12px, set 16px at 1.25 and
49
+ * stand 36px tall (T149, T154), where ours pad `space-3` (8px at normal), set
50
+ * an inherited leading, and ride the control ladder's `sm` rung (40px). Each
51
+ * falls back to the class it replaced.
52
+ */
53
+ const OPTION_PAD = "px-[calc(var(--cue-space-3)*var(--cue-style-option-pad,1))]";
54
+ /** A listbox row's leading. */
55
+ const OPTION_LEADING = "leading-[var(--cue-style-option-leading,inherit)]";
56
+ /** A listbox row's height. */
57
+ const OPTION_HEIGHT = "h-[var(--cue-style-option-height,var(--cue-control-sm))]";
58
+ /**
59
+ * A selected row's ground (round 6, spec §11, lane R6.K:
60
+ * `style-option-selected-ground`), falling back to the `transparent` a
61
+ * selected row drew: the recipe above marks selection by ink alone.
62
+ * replit.com's credit-tier listbox fills its selected row with a warm tint,
63
+ * #f5e7e2, under a deep accent ink (K147).
64
+ */
65
+ const OPTION_SELECTED_GROUND = "data-[selected]:bg-[color:var(--cue-style-option-selected-ground,transparent)]";
66
+ /**
67
+ * A row that is selected *and* highlighted — the row a select opens on, and
68
+ * the selected row under the pointer — keeps the highlight ground it drew
69
+ * before `style-option-selected-ground` existed. The name's fallback here is
70
+ * the highlight's own chain, and the two attributes together outrank either
71
+ * alone, so the order Tailwind emits `data-[selected]` and `data-[highlighted]`
72
+ * in cannot decide it. A set that names a selected ground (Kiln) paints it
73
+ * under the pointer too. The closing pass's full runs found the gap
74
+ * (T112.ground): with {@link OPTION_SELECTED_GROUND} alone, the open row lost
75
+ * its highlight in every Look but Kiln, and in no Look at all.
76
+ */
77
+ const OPTION_SELECTED_HIGHLIGHT_GROUND = "data-[selected]:data-[highlighted]:bg-[color:var(--cue-style-option-selected-ground,var(--cue-style-menu-highlight,var(--cue-accent-soft)))]";
78
+ /**
79
+ * A selected row under the pointer (the closing pass, lane R6.G:
80
+ * `style-option-selected-hover-ground`), falling back to what the row paints
81
+ * selected and highlighted ({@link OPTION_SELECTED_HIGHLIGHT_GROUND}), which a
82
+ * pointer over it always is. A list opens with its selected row highlighted, so
83
+ * a set that grounds that row needs the pointer's own ground to answer a hover:
84
+ * agent-native.com's selected option sits on its raised ground, #ffffff /
85
+ * #0f0f0f, until the pointer paints its hover fill over it (G143). `hover:` is
86
+ * the pointer's alone, so a list opened from the keyboard keeps the selected
87
+ * ground, and the third attribute outranks the two above.
88
+ */
89
+ const OPTION_SELECTED_POINTER_GROUND = "data-[selected]:data-[highlighted]:hover:bg-[color:var(--cue-style-option-selected-hover-ground,var(--cue-style-option-selected-ground,var(--cue-style-menu-highlight,var(--cue-accent-soft))))]";
90
+ /**
91
+ * A listbox popup's own padding (lane R6.K: `style-listbox-pad`, PAD2),
92
+ * falling back to the `space-1` block and `0` inline it drew (`py-(--cue-space-1)`).
93
+ * replit.com's listbox pads 4px all round, so its rows sit inside the popup's
94
+ * edge (K146). Read by `Select`'s popup and the listbox family's
95
+ * (`forms/_listbox.ts`).
96
+ */
97
+ const LISTBOX_PAD = "p-[var(--cue-style-listbox-pad,var(--cue-space-1)_0)]";
41
98
  //#endregion
42
- export { OPTION_ROW };
99
+ export { LISTBOX_PAD, OPTION_HEIGHT, OPTION_LEADING, OPTION_PAD, OPTION_ROW, OPTION_SELECTED_GROUND, OPTION_SELECTED_HIGHLIGHT_GROUND, OPTION_SELECTED_POINTER_GROUND };
@@ -0,0 +1,15 @@
1
+ //#region src/system/_style-otp.ts
2
+ /**
3
+ * The gap between an OTP field's slots (round 6, spec §11, lane R6.P:
4
+ * `style-otp-gap`), falling back to the `space-2` it drew. coss.com/ui sets its
5
+ * slots 8px apart (P166.gap).
6
+ *
7
+ * **Optional** (spec §3.0): each name is declared by `porcelain` alone and each
8
+ * reader falls back to what the component drew. Its own module for docgen's
9
+ * reason: one component's tokens per file.
10
+ *
11
+ * @internal Not part of the public API.
12
+ */
13
+ const OTP_GAP = "gap-[var(--cue-style-otp-gap,var(--cue-space-2))]";
14
+ //#endregion
15
+ export { OTP_GAP };
@@ -0,0 +1,18 @@
1
+ //#region src/system/_style-outline-hover.ts
2
+ /**
3
+ * An outline button's hover (round 6, spec §11, lane R6.P:
4
+ * `style-outline-hover-ground`, `style-outline-hover-edge`), falling back to
5
+ * the transparent ground and `accent` edge it drew. coss.com/ui's outline
6
+ * button fills a faint ink on hover and keeps its rim grey (P145.outline,
7
+ * P145.outline-edge).
8
+ *
9
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
10
+ * file, so only the components that read it are credited with it.
11
+ *
12
+ * @internal Not part of the public API.
13
+ */
14
+ const OUTLINE_HOVER_GROUND = "hover:bg-[color:var(--cue-style-outline-hover-ground,transparent)]";
15
+ /** @see OUTLINE_HOVER_GROUND */
16
+ const OUTLINE_HOVER_EDGE = "hover:border-[color:var(--cue-style-outline-hover-edge,var(--cue-accent))]";
17
+ //#endregion
18
+ export { OUTLINE_HOVER_EDGE, OUTLINE_HOVER_GROUND };
@@ -0,0 +1,17 @@
1
+ //#region src/system/_style-page.ts
2
+ /**
3
+ * Pagination's current page (round 6, spec §11, lane R6.P:
4
+ * `style-page-current-ground`, `style-page-current-rim`, `style-page-current-edge`),
5
+ * falling back to the `accent-soft` fill and no rim, as it drew. coss.com/ui marks the
6
+ * current page as an outline button: the surface, in a 1px rim (P167.current,
7
+ * P167.current-edge).
8
+ *
9
+ * **Optional** (spec §3.0): each name is declared by `porcelain` alone and each
10
+ * reader falls back to what the component drew. Its own module for docgen's
11
+ * reason: one component's tokens per file.
12
+ *
13
+ * @internal Not part of the public API.
14
+ */
15
+ const PAGE_CURRENT = "border-solid border-[length:var(--cue-style-page-current-rim,0px)] border-[color:var(--cue-style-page-current-edge,transparent)] bg-[color:var(--cue-style-page-current-ground,var(--cue-accent-soft))] text-accent";
16
+ //#endregion
17
+ export { PAGE_CURRENT };
@@ -0,0 +1,18 @@
1
+ //#region src/system/_style-palette.ts
2
+ /**
3
+ * The command palette's own parts (round 6, spec §11, lane R6.P): the rule under
4
+ * its search field (`style-palette-rule`), falling back to the `border` it
5
+ * drew, and its footer's block padding (`style-palette-footer-pad`), falling
6
+ * back to `space-2`. coss.com/ui draws no rule there and pads its footer 12px
7
+ * (P152.input-rule, P152.footer).
8
+ *
9
+ * **Optional** (spec §3.0). Its own module for docgen's reason: one token per
10
+ * file, so only the components that read it are credited with it.
11
+ *
12
+ * @internal Not part of the public API.
13
+ */
14
+ const PALETTE_RULE = "border-[color:var(--cue-style-palette-rule,var(--cue-border))]";
15
+ /** @see PALETTE_RULE */
16
+ const PALETTE_FOOTER_PAD = "py-[var(--cue-style-palette-footer-pad,var(--cue-space-2))]";
17
+ //#endregion
18
+ export { PALETTE_FOOTER_PAD, PALETTE_RULE };