@ponchia/ui 0.5.0 → 0.6.3

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 (196) hide show
  1. package/CHANGELOG.md +386 -4
  2. package/MIGRATIONS.json +14 -0
  3. package/README.md +29 -6
  4. package/annotations/index.d.ts +398 -276
  5. package/annotations/index.d.ts.map +1 -0
  6. package/annotations/index.js +350 -77
  7. package/behaviors/carousel.d.ts +28 -0
  8. package/behaviors/carousel.d.ts.map +1 -0
  9. package/behaviors/carousel.js +20 -16
  10. package/behaviors/combobox.d.ts +40 -0
  11. package/behaviors/combobox.d.ts.map +1 -0
  12. package/behaviors/combobox.js +111 -29
  13. package/behaviors/command.d.ts +41 -0
  14. package/behaviors/command.d.ts.map +1 -0
  15. package/behaviors/command.js +27 -15
  16. package/behaviors/connectors.d.ts +17 -0
  17. package/behaviors/connectors.d.ts.map +1 -0
  18. package/behaviors/connectors.js +7 -5
  19. package/behaviors/crosshair.d.ts +42 -0
  20. package/behaviors/crosshair.d.ts.map +1 -0
  21. package/behaviors/crosshair.js +23 -6
  22. package/behaviors/dialog.d.ts +20 -0
  23. package/behaviors/dialog.d.ts.map +1 -0
  24. package/behaviors/dialog.js +6 -2
  25. package/behaviors/disclosure.d.ts +10 -0
  26. package/behaviors/disclosure.d.ts.map +1 -0
  27. package/behaviors/disclosure.js +6 -2
  28. package/behaviors/dismissible.d.ts +10 -0
  29. package/behaviors/dismissible.d.ts.map +1 -0
  30. package/behaviors/dismissible.js +6 -2
  31. package/behaviors/forms.d.ts +27 -0
  32. package/behaviors/forms.d.ts.map +1 -0
  33. package/behaviors/forms.js +54 -13
  34. package/behaviors/glyph.d.ts +14 -0
  35. package/behaviors/glyph.d.ts.map +1 -0
  36. package/behaviors/glyph.js +28 -5
  37. package/behaviors/index.d.ts +31 -237
  38. package/behaviors/index.d.ts.map +1 -0
  39. package/behaviors/index.js +17 -0
  40. package/behaviors/inert.d.ts +20 -0
  41. package/behaviors/inert.d.ts.map +1 -0
  42. package/behaviors/inert.js +46 -0
  43. package/behaviors/internal.d.ts +25 -0
  44. package/behaviors/internal.d.ts.map +1 -0
  45. package/behaviors/internal.js +77 -1
  46. package/behaviors/legend.d.ts +35 -0
  47. package/behaviors/legend.d.ts.map +1 -0
  48. package/behaviors/legend.js +32 -2
  49. package/behaviors/menu.d.ts +16 -0
  50. package/behaviors/menu.d.ts.map +1 -0
  51. package/behaviors/menu.js +6 -2
  52. package/behaviors/modal.d.ts +41 -0
  53. package/behaviors/modal.d.ts.map +1 -0
  54. package/behaviors/modal.js +124 -0
  55. package/behaviors/popover.d.ts +28 -0
  56. package/behaviors/popover.d.ts.map +1 -0
  57. package/behaviors/popover.js +78 -7
  58. package/behaviors/spotlight.d.ts +17 -0
  59. package/behaviors/spotlight.d.ts.map +1 -0
  60. package/behaviors/spotlight.js +7 -5
  61. package/behaviors/table.d.ts +36 -0
  62. package/behaviors/table.d.ts.map +1 -0
  63. package/behaviors/table.js +84 -17
  64. package/behaviors/tabs.d.ts +20 -0
  65. package/behaviors/tabs.d.ts.map +1 -0
  66. package/behaviors/tabs.js +17 -14
  67. package/behaviors/theme.d.ts +54 -0
  68. package/behaviors/theme.d.ts.map +1 -0
  69. package/behaviors/theme.js +22 -3
  70. package/behaviors/toast.d.ts +49 -0
  71. package/behaviors/toast.d.ts.map +1 -0
  72. package/behaviors/toast.js +47 -3
  73. package/classes/classes.json +2527 -0
  74. package/classes/index.d.ts +134 -15
  75. package/classes/index.js +280 -80
  76. package/classes/vscode.css-custom-data.json +12 -0
  77. package/connectors/index.d.ts +201 -69
  78. package/connectors/index.d.ts.map +1 -0
  79. package/connectors/index.js +142 -25
  80. package/css/app.css +69 -13
  81. package/css/base.css +15 -10
  82. package/css/bullet.css +108 -0
  83. package/css/code.css +98 -0
  84. package/css/connectors.css +17 -0
  85. package/css/content.css +22 -3
  86. package/css/crosshair.css +7 -7
  87. package/css/dataviz.css +5 -1
  88. package/css/diff.css +153 -0
  89. package/css/disclosure.css +53 -7
  90. package/css/dots.css +94 -7
  91. package/css/feedback.css +97 -7
  92. package/css/forms.css +113 -4
  93. package/css/legend.css +16 -9
  94. package/css/marks.css +38 -8
  95. package/css/motion.css +98 -53
  96. package/css/navigation.css +7 -0
  97. package/css/overlay.css +90 -3
  98. package/css/primitives.css +158 -13
  99. package/css/report.css +73 -56
  100. package/css/sidenote.css +67 -0
  101. package/css/site.css +16 -2
  102. package/css/sources.css +43 -1
  103. package/css/spark.css +62 -0
  104. package/css/spotlight.css +1 -1
  105. package/css/table.css +9 -2
  106. package/css/term.css +110 -0
  107. package/css/textref.css +63 -0
  108. package/css/toc.css +91 -0
  109. package/css/tokens.css +49 -1
  110. package/css/tree.css +134 -0
  111. package/css/workbench.css +1 -1
  112. package/dist/bronto.css +1 -1
  113. package/dist/css/analytical.css +1 -1
  114. package/dist/css/app.css +1 -1
  115. package/dist/css/base.css +1 -1
  116. package/dist/css/bullet.css +1 -0
  117. package/dist/css/code.css +1 -0
  118. package/dist/css/connectors.css +1 -1
  119. package/dist/css/content.css +1 -1
  120. package/dist/css/crosshair.css +1 -1
  121. package/dist/css/diff.css +1 -0
  122. package/dist/css/disclosure.css +1 -1
  123. package/dist/css/dots.css +1 -1
  124. package/dist/css/feedback.css +1 -1
  125. package/dist/css/forms.css +1 -1
  126. package/dist/css/legend.css +1 -1
  127. package/dist/css/marks.css +1 -1
  128. package/dist/css/motion.css +1 -1
  129. package/dist/css/navigation.css +1 -1
  130. package/dist/css/overlay.css +1 -1
  131. package/dist/css/primitives.css +1 -1
  132. package/dist/css/report.css +1 -1
  133. package/dist/css/sidenote.css +1 -0
  134. package/dist/css/site.css +1 -1
  135. package/dist/css/sources.css +1 -1
  136. package/dist/css/spark.css +1 -0
  137. package/dist/css/spotlight.css +1 -1
  138. package/dist/css/table.css +1 -1
  139. package/dist/css/term.css +1 -0
  140. package/dist/css/textref.css +1 -0
  141. package/dist/css/toc.css +1 -0
  142. package/dist/css/tokens.css +1 -1
  143. package/dist/css/tree.css +1 -0
  144. package/dist/css/workbench.css +1 -1
  145. package/docs/adr/0003-theme-model.md +1 -1
  146. package/docs/annotations.md +133 -14
  147. package/docs/architecture.md +49 -6
  148. package/docs/bullet.md +78 -0
  149. package/docs/code.md +76 -0
  150. package/docs/contrast.md +116 -92
  151. package/docs/d2.md +196 -0
  152. package/docs/diff.md +146 -0
  153. package/docs/legends.md +23 -3
  154. package/docs/marks.md +9 -2
  155. package/docs/mermaid.md +169 -0
  156. package/docs/reference.md +201 -26
  157. package/docs/reporting.md +416 -57
  158. package/docs/sidenote.md +64 -0
  159. package/docs/sources.md +27 -0
  160. package/docs/spark.md +78 -0
  161. package/docs/stability.md +10 -2
  162. package/docs/term.md +81 -0
  163. package/docs/textref.md +78 -0
  164. package/docs/theming.md +44 -5
  165. package/docs/toc.md +83 -0
  166. package/docs/tree.md +74 -0
  167. package/docs/usage.md +354 -16
  168. package/docs/vega.md +244 -0
  169. package/docs/workbench.md +7 -1
  170. package/glyphs/glyphs.js +13 -5
  171. package/llms.txt +285 -14
  172. package/package.json +95 -17
  173. package/qwik/index.d.ts +44 -59
  174. package/qwik/index.d.ts.map +1 -0
  175. package/qwik/index.js +65 -3
  176. package/react/index.d.ts +41 -61
  177. package/react/index.d.ts.map +1 -0
  178. package/react/index.js +63 -3
  179. package/solid/index.d.ts +68 -61
  180. package/solid/index.d.ts.map +1 -0
  181. package/solid/index.js +66 -3
  182. package/tokens/d2.d.ts +38 -0
  183. package/tokens/d2.js +71 -0
  184. package/tokens/d2.json +43 -0
  185. package/tokens/index.d.ts +5 -5
  186. package/tokens/index.js +15 -1
  187. package/tokens/index.json +9 -0
  188. package/tokens/mermaid.d.ts +23 -0
  189. package/tokens/mermaid.js +181 -0
  190. package/tokens/mermaid.json +163 -0
  191. package/tokens/resolved.json +45 -1
  192. package/tokens/skins.js +3 -2
  193. package/tokens/tokens.dtcg.json +26 -0
  194. package/tokens/vega.d.ts +34 -0
  195. package/tokens/vega.js +155 -0
  196. package/tokens/vega.json +179 -0
package/css/diff.css ADDED
@@ -0,0 +1,153 @@
1
+ /* ==========================================================================
2
+ diff — opt-in line/row change-review grammar.
3
+
4
+ The review counterpart to the report layer: marks call out a sentence, diff
5
+ calls out what CHANGED. A CSS-grid gutter grammar for added / removed /
6
+ context rows with a redundant +/− sign glyph (so the meaning survives forced
7
+ colours and print, where the tint is dropped), tone tints, and tabular
8
+ line-number gutters. Not imported by core.css.
9
+
10
+ Boundary: the HOST supplies pre-classified rows — it owns tokenizing, hunk
11
+ computation, and row alignment; Bronto only paints. The moment this parsed or
12
+ aligned source it would cross the line that deleted the bar renderer in
13
+ 0.6.0. Pairs with `.ui-compare--2up` and the `.ui-src` provenance pill.
14
+
15
+ Unified (default): rows are direct children of `.ui-diff` (or a
16
+ `.ui-diff__hunk` rowgroup); columns are [old-ln] [new-ln] [code].
17
+ Split: `.ui-diff--split` holds two `.ui-diff__pane` columns, each [ln] [code];
18
+ the host emits the matching rows per side.
19
+
20
+ Long lines wrap (no horizontal scroll) so the surface prints cleanly; line
21
+ numbers pin to the top of a wrapped line. Line numbers are `user-select:none`
22
+ and should be `aria-hidden` in markup — the `__code` carries the content.
23
+ ========================================================================== */
24
+
25
+ .ui-diff {
26
+ --diff-add-bg: color-mix(in srgb, var(--success) 14%, transparent);
27
+ --diff-remove-bg: color-mix(in srgb, var(--danger) 14%, transparent);
28
+ --diff-add-ink: var(--success);
29
+ --diff-remove-ink: var(--danger);
30
+
31
+ border: 1px solid var(--line);
32
+ border-radius: var(--radius-sm);
33
+ display: grid;
34
+ font-family: var(--mono);
35
+ font-size: var(--text-xs);
36
+ grid-template-columns: auto auto minmax(0, 1fr);
37
+ line-height: 1.6;
38
+ overflow: hidden;
39
+ }
40
+
41
+ /* Split view: two independent panes side by side. Each pane is its own
42
+ [ln] [code] grid; the host aligns rows across panes (its job). */
43
+ .ui-diff--split {
44
+ grid-template-columns: 1fr 1fr;
45
+ }
46
+
47
+ .ui-diff__pane {
48
+ display: grid;
49
+ grid-template-columns: auto minmax(0, 1fr);
50
+ min-inline-size: 0;
51
+ }
52
+
53
+ .ui-diff--split > .ui-diff__pane + .ui-diff__pane {
54
+ border-inline-start: 1px solid var(--line);
55
+ }
56
+
57
+ /* A hunk groups rows under an optional header without breaking the grid:
58
+ display:contents keeps its rows as the grid's own items. */
59
+ .ui-diff__hunk {
60
+ display: contents;
61
+ }
62
+
63
+ /* Rows are layout-transparent — their cells are the real grid items, so the
64
+ tone tint paints on the cells (a display:contents row generates no box, and
65
+ the custom properties still inherit down the DOM to the cells). */
66
+ .ui-diff__row {
67
+ display: contents;
68
+ }
69
+
70
+ /* The hunk / file header spans every column. */
71
+ .ui-diff__head {
72
+ background: var(--surface-2);
73
+ color: var(--text-dim);
74
+ grid-column: 1 / -1;
75
+ padding: var(--space-2xs) var(--space-sm);
76
+ }
77
+
78
+ .ui-diff__ln {
79
+ align-self: start;
80
+ color: var(--text-dim);
81
+ font-variant-numeric: tabular-nums;
82
+ padding: 0 var(--space-sm);
83
+ text-align: end;
84
+ /* stylelint-disable-next-line property-no-vendor-prefix -- WebKit still requires the prefixed slot for this selection opt-out. */
85
+ -webkit-user-select: none;
86
+ user-select: none;
87
+ }
88
+
89
+ .ui-diff__code {
90
+ overflow-wrap: anywhere;
91
+ padding: 0 var(--space-sm);
92
+ white-space: pre-wrap;
93
+ }
94
+
95
+ /* The redundant sign glyph in the code gutter — a non-colour channel, so add /
96
+ remove still read once the tint is dropped (forced colours, print economy).
97
+ Context defaults to a non-breaking space so the code column stays aligned. */
98
+ .ui-diff__code::before {
99
+ color: var(--diff-tint, var(--text-dim));
100
+ content: var(--diff-sign, '\00a0');
101
+ display: inline-block;
102
+ inline-size: 1ch;
103
+ margin-inline-end: var(--space-2xs);
104
+ /* stylelint-disable-next-line property-no-vendor-prefix -- WebKit still requires the prefixed slot for this selection opt-out. */
105
+ -webkit-user-select: none;
106
+ user-select: none;
107
+ }
108
+
109
+ .ui-diff__row--add {
110
+ --diff-sign: '+';
111
+ --diff-tint: var(--diff-add-ink);
112
+ }
113
+
114
+ .ui-diff__row--remove {
115
+ --diff-sign: '\2212'; /* − U+2212 minus sign (decorative; not copied) */
116
+ --diff-tint: var(--diff-remove-ink);
117
+ }
118
+
119
+ .ui-diff__row--context {
120
+ --diff-sign: '\00a0';
121
+ }
122
+
123
+ .ui-diff__row--add > .ui-diff__ln,
124
+ .ui-diff__row--add > .ui-diff__code {
125
+ background: var(--diff-add-bg);
126
+ }
127
+
128
+ .ui-diff__row--remove > .ui-diff__ln,
129
+ .ui-diff__row--remove > .ui-diff__code {
130
+ background: var(--diff-remove-bg);
131
+ }
132
+
133
+ /* Forced colours drop the tint — the +/− glyph already carries the channel; add
134
+ an inline-start border on the changed code cell as a second, colour-free cue. */
135
+ @media (forced-colors: active) {
136
+ .ui-diff__row--add > .ui-diff__code,
137
+ .ui-diff__row--remove > .ui-diff__code {
138
+ border-inline-start: 2px solid currentColor;
139
+ }
140
+ }
141
+
142
+ /* Print: the tints are meaning-carrying backgrounds, so force them through the
143
+ print "economy" default that would otherwise drop them. */
144
+ @media print {
145
+ .ui-diff__head,
146
+ .ui-diff__row--add > .ui-diff__ln,
147
+ .ui-diff__row--add > .ui-diff__code,
148
+ .ui-diff__row--remove > .ui-diff__ln,
149
+ .ui-diff__row--remove > .ui-diff__code {
150
+ -webkit-print-color-adjust: exact;
151
+ print-color-adjust: exact;
152
+ }
153
+ }
@@ -44,11 +44,29 @@
44
44
  border-color var(--duration-fast) var(--ease-standard);
45
45
  }
46
46
 
47
+ /* Coarse-pointer tap-target floor (~2.9rem ≈ 44px), matching inputs/sitenav —
48
+ tabs are easy to mis-tap on touch (WCAG 2.5.8 — C24). */
49
+ @media (pointer: coarse) {
50
+ .ui-tab {
51
+ min-block-size: 2.9rem;
52
+ }
53
+ }
54
+
47
55
  .ui-tab.is-active {
48
56
  border-block-end-color: var(--accent);
49
57
  color: var(--accent-text);
50
58
  }
51
59
 
60
+ /* Forced-colors re-assert MUST sit after the default above (same specificity,
61
+ @media adds none) or the accent default wins and the selected tab loses its
62
+ only cue. Moved here from base.css, an earlier bundle leaf. (a11y review C10.) */
63
+ @media (forced-colors: active) {
64
+ .ui-tab.is-active {
65
+ border-block-end-color: Highlight;
66
+ color: Highlight;
67
+ }
68
+ }
69
+
52
70
  .ui-tab:focus-visible {
53
71
  /* An inset box, deliberately distinct from the .is-active bottom-border
54
72
  so focus ≠ selection for low-vision keyboard users: the global
@@ -199,7 +217,7 @@
199
217
 
200
218
  .ui-segmented__option:has(input:focus-visible) {
201
219
  outline: 2px solid var(--focus-ring);
202
- outline-offset: 2px;
220
+ outline-offset: -2px;
203
221
  }
204
222
 
205
223
  @media (hover: hover) {
@@ -240,7 +258,7 @@
240
258
  inline-size: 0.22rem;
241
259
  }
242
260
 
243
- .ui-breadcrumb__item[aria-current] {
261
+ .ui-breadcrumb__item[aria-current]:not([aria-current='false']) {
244
262
  color: var(--text);
245
263
  }
246
264
 
@@ -285,23 +303,51 @@
285
303
  color var(--duration-fast) var(--ease-standard);
286
304
  }
287
305
 
288
- .ui-pagination__item.is-active {
306
+ /* Active page keys on BOTH `.is-active` and `[aria-current]` — usage.md calls
307
+ aria-current "the framework rule", and every nav sibling (breadcrumb, sitenav,
308
+ app-nav) highlights on it, so a pagination author who sets only aria-current
309
+ must still get the highlight. (component audit C17.) */
310
+ .ui-pagination__item.is-active,
311
+ .ui-pagination__item[aria-current]:not([aria-current='false']) {
289
312
  border-color: var(--accent);
290
313
  color: var(--accent-text);
291
314
  }
292
315
 
293
- .ui-pagination__item[aria-disabled='true'] {
316
+ /* Disabled covers BOTH the native `<button disabled>` the demo ships and the
317
+ `aria-disabled="true"` ARIA path. `pointer-events: none` blocks POINTER
318
+ activation only — a focused aria-disabled item still fires on Enter/Space
319
+ (CSS can't intercept keys). For a fully-inert control prefer native
320
+ `<button disabled>`, run `initDisabledGuard()` (intercepts Enter/Space), or
321
+ pair aria-disabled with `tabindex="-1"`. See docs/usage.md "Disabled vs
322
+ aria-disabled". (audit C4.) */
323
+ .ui-pagination__item[aria-disabled='true'],
324
+ .ui-pagination__item:disabled {
294
325
  cursor: not-allowed;
295
326
  opacity: 0.4;
327
+ pointer-events: none;
296
328
  }
297
329
 
298
330
  @media (hover: hover) {
299
- .ui-pagination__item:not(.is-active, [aria-disabled='true']):hover {
331
+ .ui-pagination__item:not(
332
+ .is-active,
333
+ [aria-current]:not([aria-current='false']),
334
+ [aria-disabled='true'],
335
+ :disabled
336
+ ):hover {
300
337
  border-color: var(--line-strong);
301
338
  color: var(--text);
302
339
  }
303
340
  }
304
341
 
342
+ /* Coarse-pointer tap-target floor, matching inputs/sitenav (~2.9rem ≈ 44px) —
343
+ pagination controls are easy to mis-tap on touch (WCAG 2.5.8 — C24). */
344
+ @media (pointer: coarse) {
345
+ .ui-pagination__item {
346
+ min-block-size: 2.9rem;
347
+ min-inline-size: 2.9rem;
348
+ }
349
+ }
350
+
305
351
  /* --- Avatar — sharp, monospace initials or image --- */
306
352
 
307
353
  .ui-avatar {
@@ -429,8 +475,8 @@
429
475
  .ui-carousel__prev::before,
430
476
  .ui-carousel__next::before {
431
477
  block-size: 0.5rem;
432
- border-block-start: 1.5px solid currentColor;
433
- border-inline-end: 1.5px solid currentColor;
478
+ border-block-start: 1.5px solid currentcolor;
479
+ border-inline-end: 1.5px solid currentcolor;
434
480
  content: '';
435
481
  inline-size: 0.5rem;
436
482
  }
package/css/dots.css CHANGED
@@ -281,6 +281,13 @@
281
281
  transform: rotate(315deg) translateY(calc(var(--ds-box) / -2 + var(--ds-dot) / 2));
282
282
  }
283
283
 
284
+ /* The comet expects exactly 8 `<i>`; a 9th+ child has no rotation rule and
285
+ would pile up dead-centre. Hide the overflow so extra children fail safe
286
+ rather than rendering a stray static dot (C26). */
287
+ .ui-dotspinner i:nth-child(n + 9) {
288
+ display: none;
289
+ }
290
+
284
291
  .ui-dotspinner--sm {
285
292
  --ds-box: 1.05rem;
286
293
  --ds-dot: 0.18rem;
@@ -341,14 +348,20 @@
341
348
  animation-delay: 0.63s;
342
349
  }
343
350
 
344
- /* Matrix-reveal wrapper — content wipes in left→right on .is-in. */
345
- .ui-matrix {
346
- clip-path: inset(0 100% 0 0);
347
- transition: clip-path var(--duration-slow) var(--ease-out);
348
- }
351
+ /* Matrix-reveal wrapper — content wipes in left→right on .is-in. Gate the
352
+ clipped from-state on `scripting: enabled`: with JS off, `.is-in` is never
353
+ toggled, so without the gate the content stays permanently clipped away and
354
+ invisible to every no-JS/static/print reader. Same graceful default as
355
+ `.ui-reveal`. (component audit C12.) */
356
+ @media (scripting: enabled) {
357
+ .ui-matrix {
358
+ clip-path: inset(0 100% 0 0);
359
+ transition: clip-path var(--duration-slow) var(--ease-out);
360
+ }
349
361
 
350
- .ui-matrix.is-in {
351
- clip-path: inset(0 0 0 0);
362
+ .ui-matrix.is-in {
363
+ clip-path: inset(0 0 0 0);
364
+ }
352
365
  }
353
366
 
354
367
  @media (prefers-reduced-motion: reduce) {
@@ -370,3 +383,77 @@
370
383
  clip-path: none;
371
384
  }
372
385
  }
386
+
387
+ /* Forced-colors (Windows HCM): semantic status dots and hot/accent matrix
388
+ cells encode meaning purely via background-color, which collapses to one
389
+ system colour under HCM (WCAG 1.4.1). Opt out of forced-color remapping and
390
+ apply four visually-distinct system colours so the signals stay
391
+ differentiable. */
392
+ @media (forced-colors: active) {
393
+ .ui-dot--success {
394
+ forced-color-adjust: none;
395
+ background: LinkText;
396
+ }
397
+
398
+ .ui-dot--warning {
399
+ forced-color-adjust: none;
400
+ background: Mark;
401
+ }
402
+
403
+ .ui-dot--danger {
404
+ forced-color-adjust: none;
405
+ background: Highlight;
406
+ }
407
+
408
+ .ui-dot--info {
409
+ forced-color-adjust: none;
410
+ background: ButtonText;
411
+ }
412
+
413
+ /* Brand/live dots aren't status tones, but they still encode meaning via
414
+ background-color alone, which HCM flattens. Keep them on a distinct,
415
+ opted-out system colour for completeness. (audit C31.) */
416
+ .ui-dot--accent,
417
+ .ui-dot--live {
418
+ forced-color-adjust: none;
419
+ background: LinkText;
420
+ }
421
+
422
+ .ui-dot--live::after {
423
+ border-color: LinkText;
424
+ }
425
+
426
+ /* The masked one-node icon paints `background: currentcolor` through an SVG
427
+ mask. Under HCM, forced-color-adjust:auto can drop the mask fill so the
428
+ glyph vanishes (white-on-white) — yet .ui-icon is the recommended
429
+ icon-at-scale path AND backs .ui-legend__symbol, and the print block
430
+ already special-cases it. Opt out and pin the fill to the system text
431
+ colour so the glyph stays visible. (audit C1.) */
432
+ .ui-icon {
433
+ forced-color-adjust: none;
434
+ background: CanvasText;
435
+ }
436
+
437
+ .ui-dotmatrix__cell--hot {
438
+ forced-color-adjust: none;
439
+ background: Highlight;
440
+ }
441
+
442
+ .ui-dotmatrix__cell--accent {
443
+ forced-color-adjust: none;
444
+ background: LinkText;
445
+ }
446
+ }
447
+
448
+ /* Print: the dot surfaces carry data (heatmap cells, the segmented meter, the
449
+ status dot, the masked glyph), so their painted fills must survive the print
450
+ "economy" default that drops backgrounds. */
451
+ @media print {
452
+ .ui-dotmatrix__cell,
453
+ .ui-dotbar i,
454
+ .ui-dot,
455
+ .ui-icon {
456
+ -webkit-print-color-adjust: exact;
457
+ print-color-adjust: exact;
458
+ }
459
+ }
package/css/feedback.css CHANGED
@@ -4,6 +4,19 @@
4
4
  never a fill. Nothing-flat, hairline, sharp.
5
5
  ========================================================================== */
6
6
 
7
+ /* `--value` drives the progress/meter fill width: a UNITLESS number 0–100,
8
+ never a percentage. Registering it as `<number>` makes that contract real —
9
+ a stray `--value: 50%` is invalid against the typed syntax and falls back to
10
+ the initial `0` (empty bar) instead of poisoning the `clamp()` and painting a
11
+ FULL bar (the old failure mode). It inherits so the value set on the host
12
+ `.ui-meter` / `.ui-progress` cascades to the inner `__fill`/`__bar`.
13
+ (component audit C8.) */
14
+ @property --value {
15
+ syntax: '<number>';
16
+ inherits: true;
17
+ initial-value: 0;
18
+ }
19
+
7
20
  /* --- Alert / callout — inline, dismissible-compatible --- */
8
21
 
9
22
  .ui-alert {
@@ -50,7 +63,7 @@
50
63
  margin: 0;
51
64
  }
52
65
 
53
- .ui-alert__dismiss {
66
+ .ui-alert__close {
54
67
  background: transparent;
55
68
  border: 0;
56
69
  color: var(--text-dim);
@@ -62,7 +75,7 @@
62
75
  padding: 0.1rem 0.3rem;
63
76
  }
64
77
 
65
- .ui-alert:has(.ui-alert__dismiss) {
78
+ .ui-alert:has(.ui-alert__close) {
66
79
  grid-template-columns: auto 1fr auto;
67
80
  }
68
81
 
@@ -107,7 +120,7 @@
107
120
  }
108
121
 
109
122
  @media (hover: hover) {
110
- .ui-alert__dismiss:hover {
123
+ .ui-alert__close:hover {
111
124
  color: var(--text);
112
125
  }
113
126
  }
@@ -212,8 +225,27 @@
212
225
  line-height: 1;
213
226
  }
214
227
 
215
- .ui-toast__close:hover {
216
- color: var(--text);
228
+ /* Touch: enlarge the dismiss/close hit areas to the project's coarse-pointer
229
+ tap-target floor (2.9rem, as in primitives.css / forms.css) without changing
230
+ the desktop glyph size. The box is centred so the glyph stays put. */
231
+ @media (pointer: coarse) {
232
+ .ui-alert__close,
233
+ .ui-toast__close {
234
+ display: inline-grid;
235
+ place-items: center;
236
+ min-block-size: 2.9rem;
237
+ min-inline-size: 2.9rem;
238
+ }
239
+
240
+ .ui-alert__close {
241
+ padding: 0;
242
+ }
243
+ }
244
+
245
+ @media (hover: hover) {
246
+ .ui-toast__close:hover {
247
+ color: var(--text);
248
+ }
217
249
  }
218
250
 
219
251
  .ui-toast--accent::before {
@@ -420,6 +452,7 @@
420
452
  .ui-progress__bar {
421
453
  background: var(--accent);
422
454
  block-size: 100%;
455
+ display: block;
423
456
  transition: inline-size var(--duration-base) var(--ease-out);
424
457
  inline-size: calc(clamp(0, var(--value, 0), 100) * 1%);
425
458
  }
@@ -433,6 +466,18 @@
433
466
  @media (prefers-reduced-motion: reduce) {
434
467
  .ui-progress--indeterminate .ui-progress__bar {
435
468
  animation-duration: 0.01ms;
469
+
470
+ /* A still, solid, full-width bar reads as "100% complete" — the opposite of
471
+ indeterminate. Fall back to a static diagonal hatch that fills the track
472
+ (so it's clearly active) but doesn't read as done. AT is covered via
473
+ aria-busy. (audit C26.) */
474
+ background: repeating-linear-gradient(
475
+ -45deg,
476
+ var(--accent) 0,
477
+ var(--accent) 0.3rem,
478
+ color-mix(in srgb, var(--accent) 35%, transparent) 0.3rem,
479
+ color-mix(in srgb, var(--accent) 35%, transparent) 0.6rem
480
+ );
436
481
  inset-inline-start: 0;
437
482
  inline-size: 100%;
438
483
  }
@@ -447,7 +492,9 @@
447
492
  (task progress, can be indeterminate), a meter shows a measured static
448
493
  value for data display (coverage, capacity, a KPI against a target).
449
494
  Drive the fill with the same --value knob as progress; tone the fill by
450
- threshold. Author role="meter" + aria-valuenow/min/max for AT. --- */
495
+ threshold. Author role="meter" + aria-valuenow/min/max for AT but role=meter
496
+ has uneven AT support, so keep the visible .ui-meter__label/__value (they are
497
+ the real channel, not just decoration). (component audit C25.) --- */
451
498
 
452
499
  .ui-meter {
453
500
  background: var(--panel-soft);
@@ -465,6 +512,7 @@
465
512
  .ui-meter__fill {
466
513
  background: var(--text-dim);
467
514
  block-size: 100%;
515
+ display: block;
468
516
  transition: inline-size var(--duration-base) var(--ease-out);
469
517
  inline-size: calc(clamp(0, var(--value, 0), 100) * 1%);
470
518
  }
@@ -485,6 +533,10 @@
485
533
  background: var(--danger);
486
534
  }
487
535
 
536
+ .ui-meter--info .ui-meter__fill {
537
+ background: var(--info);
538
+ }
539
+
488
540
  /* --- Steps — progress through a multi-step flow. Use an <ol>; the
489
541
  current step is aria-current="step" (no class), completed steps take
490
542
  --done. Counter-numbered markers, hairline connectors. --- */
@@ -509,7 +561,12 @@
509
561
  font-size: var(--text-xs);
510
562
  gap: 0.5rem;
511
563
  letter-spacing: var(--tracking-wide);
512
- min-inline-size: max-content;
564
+
565
+ /* Prefer the natural one-line width, but never wider than the container: a
566
+ long step label at `max-content` couldn't shrink and overflowed the page on
567
+ narrow viewports (tabs scroll; steps didn't). Capping at 100% lets an
568
+ over-long label wrap instead of overflowing. (component audit C18.) */
569
+ min-inline-size: min(100%, max-content);
513
570
  text-transform: uppercase;
514
571
  }
515
572
 
@@ -553,3 +610,36 @@
553
610
  border-color: var(--accent);
554
611
  color: var(--button-text);
555
612
  }
613
+
614
+ /* Print: the progress/meter fill is the data (a measured proportion), so its
615
+ painted background must survive the print "economy" default. The fill tokens
616
+ are re-pointed to print-legible inks by the global print remap in base.css. */
617
+ @media print {
618
+ .ui-progress__bar,
619
+ .ui-meter__fill {
620
+ -webkit-print-color-adjust: exact;
621
+ print-color-adjust: exact;
622
+ }
623
+ }
624
+
625
+ /* Forced-colors flattens the fill's tone to the system palette and can erase it
626
+ against the track, dropping the only visual cue of the measured proportion.
627
+ Re-assert a system colour so the bar stays visible; the tone's *semantic* is
628
+ carried by the author-written label beside it, not the colour. (a11y C10.)
629
+ The toned `.ui-meter--TONE .ui-meter__fill` rules are (0,2,0); the bare
630
+ `.ui-meter__fill` reset is only (0,1,0), so it lost — a toned fill stayed
631
+ `var(--TONE)` and was forced to black-on-black (component-audit C3). Match the
632
+ tone specificity here (and set `forced-color-adjust: none`) so every meter,
633
+ toned or not, paints `Highlight`, mirroring the `.ui-dot` precedent. */
634
+ @media (forced-colors: active) {
635
+ .ui-progress__bar,
636
+ .ui-meter__fill,
637
+ .ui-meter--accent .ui-meter__fill,
638
+ .ui-meter--success .ui-meter__fill,
639
+ .ui-meter--warning .ui-meter__fill,
640
+ .ui-meter--danger .ui-meter__fill,
641
+ .ui-meter--info .ui-meter__fill {
642
+ background: Highlight;
643
+ forced-color-adjust: none;
644
+ }
645
+ }