@ponchia/ui 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +322 -0
  2. package/MIGRATIONS.json +14 -0
  3. package/README.md +28 -5
  4. package/annotations/index.d.ts +398 -276
  5. package/annotations/index.d.ts.map +1 -0
  6. package/annotations/index.js +315 -45
  7. package/behaviors/carousel.js +17 -16
  8. package/behaviors/combobox.js +47 -16
  9. package/behaviors/command.js +18 -15
  10. package/behaviors/connectors.js +4 -5
  11. package/behaviors/crosshair.js +4 -5
  12. package/behaviors/dialog.js +3 -2
  13. package/behaviors/disclosure.js +3 -2
  14. package/behaviors/dismissible.js +3 -2
  15. package/behaviors/forms.js +41 -13
  16. package/behaviors/glyph.js +4 -5
  17. package/behaviors/internal.js +47 -0
  18. package/behaviors/legend.js +23 -2
  19. package/behaviors/menu.js +3 -2
  20. package/behaviors/popover.js +78 -7
  21. package/behaviors/spotlight.js +4 -5
  22. package/behaviors/table.js +39 -12
  23. package/behaviors/tabs.js +14 -14
  24. package/behaviors/theme.js +5 -3
  25. package/behaviors/toast.js +13 -1
  26. package/classes/classes.json +1857 -0
  27. package/classes/index.d.ts +28 -13
  28. package/classes/index.js +34 -18
  29. package/classes/vscode.css-custom-data.json +12 -0
  30. package/connectors/index.d.ts +189 -69
  31. package/connectors/index.d.ts.map +1 -0
  32. package/connectors/index.js +120 -24
  33. package/css/app.css +43 -13
  34. package/css/base.css +15 -10
  35. package/css/connectors.css +17 -0
  36. package/css/content.css +7 -1
  37. package/css/dataviz.css +5 -1
  38. package/css/disclosure.css +38 -6
  39. package/css/dots.css +57 -0
  40. package/css/feedback.css +60 -2
  41. package/css/forms.css +42 -1
  42. package/css/legend.css +11 -7
  43. package/css/marks.css +38 -8
  44. package/css/motion.css +24 -44
  45. package/css/navigation.css +7 -0
  46. package/css/overlay.css +31 -1
  47. package/css/primitives.css +91 -5
  48. package/css/report.css +40 -63
  49. package/css/site.css +16 -2
  50. package/css/sources.css +43 -1
  51. package/css/spotlight.css +1 -1
  52. package/css/tokens.css +36 -1
  53. package/css/workbench.css +1 -1
  54. package/dist/bronto.css +1 -1
  55. package/dist/css/analytical.css +1 -1
  56. package/dist/css/app.css +1 -1
  57. package/dist/css/base.css +1 -1
  58. package/dist/css/connectors.css +1 -1
  59. package/dist/css/content.css +1 -1
  60. package/dist/css/disclosure.css +1 -1
  61. package/dist/css/dots.css +1 -1
  62. package/dist/css/feedback.css +1 -1
  63. package/dist/css/forms.css +1 -1
  64. package/dist/css/legend.css +1 -1
  65. package/dist/css/marks.css +1 -1
  66. package/dist/css/motion.css +1 -1
  67. package/dist/css/navigation.css +1 -1
  68. package/dist/css/overlay.css +1 -1
  69. package/dist/css/primitives.css +1 -1
  70. package/dist/css/report.css +1 -1
  71. package/dist/css/site.css +1 -1
  72. package/dist/css/sources.css +1 -1
  73. package/dist/css/spotlight.css +1 -1
  74. package/dist/css/tokens.css +1 -1
  75. package/dist/css/workbench.css +1 -1
  76. package/docs/adr/0003-theme-model.md +1 -1
  77. package/docs/annotations.md +94 -14
  78. package/docs/architecture.md +50 -6
  79. package/docs/contrast.md +116 -92
  80. package/docs/d2.md +195 -0
  81. package/docs/legends.md +18 -2
  82. package/docs/marks.md +9 -2
  83. package/docs/mermaid.md +152 -0
  84. package/docs/reference.md +78 -22
  85. package/docs/reporting.md +395 -57
  86. package/docs/sources.md +27 -0
  87. package/docs/stability.md +9 -2
  88. package/docs/usage.md +101 -4
  89. package/docs/vega.md +225 -0
  90. package/docs/workbench.md +7 -1
  91. package/glyphs/glyphs.js +6 -4
  92. package/llms.txt +139 -14
  93. package/package.json +50 -12
  94. package/qwik/index.d.ts +42 -59
  95. package/qwik/index.d.ts.map +1 -0
  96. package/qwik/index.js +55 -3
  97. package/react/index.d.ts +39 -61
  98. package/react/index.d.ts.map +1 -0
  99. package/react/index.js +57 -3
  100. package/solid/index.d.ts +64 -61
  101. package/solid/index.d.ts.map +1 -0
  102. package/solid/index.js +60 -3
  103. package/tokens/d2.d.ts +38 -0
  104. package/tokens/d2.js +71 -0
  105. package/tokens/d2.json +43 -0
  106. package/tokens/index.d.ts +5 -5
  107. package/tokens/index.js +15 -1
  108. package/tokens/index.json +9 -0
  109. package/tokens/mermaid.d.ts +23 -0
  110. package/tokens/mermaid.js +181 -0
  111. package/tokens/mermaid.json +163 -0
  112. package/tokens/resolved.json +45 -1
  113. package/tokens/skins.js +3 -2
  114. package/tokens/tokens.dtcg.json +26 -0
  115. package/tokens/vega.d.ts +34 -0
  116. package/tokens/vega.js +155 -0
  117. package/tokens/vega.json +179 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,328 @@
5
5
  > `^0` / `*` wildcard does **not** protect you. See README → Versioning, and
6
6
  > the deprecation policy in CONTRIBUTING.md.
7
7
 
8
+ ## 0.6.0 — 2026-06-03
9
+
10
+ Accumulates the post-0.5.0 work: a multi-agent audit pass (accessibility
11
+ hardening, a behavior/binding scope-safety fix, codegen/gate tightening) plus a
12
+ **breaking** charting realignment. The local static-bar renderer
13
+ (`.ui-chart*`) is **removed** — a chart needs scales + data binding, which the
14
+ analytical layer refuses to own. In its place, bronto becomes a themeable target
15
+ for **Vega-Lite** (`@ponchia/ui/vega`), the same tokens-as-data path as Mermaid
16
+ and D2. The data-viz **palette** (`--chart-*`, `tokens/charts.json`) and the
17
+ **legend** layer are unchanged. Pin `~0.5` → re-pin `~0.6`; see
18
+ [`MIGRATIONS.json`](./MIGRATIONS.json) (`0.5`→`0.6`).
19
+
20
+ ### Added
21
+
22
+ - **`@ponchia/ui/vega`** (+ `vega.json`) — an on-brand Vega-Lite / Vega
23
+ [`config`](https://vega.github.io/vega-lite/docs/config.html) resolved per
24
+ theme (the idiomatic `vega-themes` shape): monochrome chrome + one rationed
25
+ accent, `range.category/ordinal/ramp/heatmap/diverging` from the CVD-safe
26
+ data-viz palette. `brontoVegaConfig(theme)`. Resolved hex (Vega bakes colours
27
+ into SVG/canvas, can't read `var()`); gated structurally **and** by a headless
28
+ render-probe that asserts the colours land on a rendered chart. Vega is the
29
+ consumer's renderer — config only, not a dependency. See `docs/vega.md`.
30
+ - **`ui-delta`** — a standalone trend/change indicator (core primitive): an
31
+ arrow glyph (the non-colour channel) plus the figure, with
32
+ `--up`/`--down`/`--flat`, and `--invert` to swap only the tone when "up" is
33
+ the bad direction (latency, error rate, cost). `ui.delta({ dir, invert })`.
34
+ - **`ui-compare`** — a fluid side-by-side / before-after layout for the report
35
+ layer (`css/report.css`): `__col`, `__head`, and `--2up`.
36
+ `ui.compare({ cols })`.
37
+ - **`@ponchia/ui/classes.json`** — the class vocabulary as language-neutral
38
+ data (`groups`/`classes`/`states`/`customProperties`), so a non-JS/non-TS
39
+ host or an external linter can validate emitted markup without executing the
40
+ ESM `cls` map or parsing the `.d.ts`. Generated from `cls`; drift-checked and
41
+ its `states`/`customProperties` gated against the stylesheet.
42
+ - **`tokens/resolved.json` `scale` block** — the resolved non-colour scales
43
+ (spacing/radius/type/z/motion, `var()` chains flattened), completing the
44
+ token contract for non-CSS hosts (previously colour-only).
45
+ - **`--display-weight` / `--display-weight-strong`** (700 / 800) — the weight of
46
+ the Doto dot-matrix display face, now a token. Themes/skins can re-tune how
47
+ heavy display text renders in one place.
48
+ - On-brand **Mermaid** (`@ponchia/ui/mermaid`, `mermaid.json`) and **D2**
49
+ (`@ponchia/ui/d2`, `d2.json`) theme maps — resolved per-theme palettes
50
+ projected from the same tokens, gated. Diagrams stay the consumer's renderer;
51
+ these are config only.
52
+ - Annotation geometry options: `connectorElbow({ mid })` (turn position along the
53
+ dominant axis), `notePlacement({ inset })` (reserve the title stroke-halo so a
54
+ placement that "fits" doesn't clip), and a `spread` half-angle on both
55
+ `connectorEndArrow` and the shared `arrowHead` kernel.
56
+ - **`brontoVegaAccent(theme)` / `brontoVegaNeutral(theme)`** (`@ponchia/ui/vega`)
57
+ — the exact per-theme hexes for `range.category`'s accent (series 1) and
58
+ neutral (last series), so spending the accent on one emphasised mark needs no
59
+ palette-index reverse-engineering.
60
+ - **`--on-accent`** token — the readable ink for a label on **any accent fill**
61
+ (button, badge, themed chart bar, a Vega/D2 node). Resolves to `--button-text`
62
+ (white on the light accent, black on the dark) and is gated ≥ 4.5:1 in
63
+ `docs/contrast.md`. Use it instead of `--accent-text`, which is the inverse
64
+ (accent-coloured text for a *neutral* background, ~1.3:1 on an accent fill).
65
+ - **`.ui-src`** standalone trust pill (`cls.src`, `css/sources.css`) — wears a
66
+ `.ui-src--*` tone (verified / reviewed / generated / unverified / stale /
67
+ conflict) on its own, for a bare trust label outside a citation or source card.
68
+ Previously the `.ui-src--*` modifiers only painted a `--src-tone` with no
69
+ standalone host, so a lone pill validated against `classes.json` yet rendered
70
+ nothing.
71
+
72
+ ### Removed
73
+
74
+ - **BREAKING: the local static bar-chart renderer (`.ui-chart`, `.ui-chart__plot`,
75
+ `__bar`, `__label`, `__track`, `__fill`, `__fallback`, `__caption`).** A chart
76
+ needs scales and data binding — out of scope for a CSS-first analytical layer
77
+ (ADR-0002). Replace with a Vega-Lite chart themed via `@ponchia/ui/vega`, or a
78
+ hand-authored token-themed inline `<svg>`, inside a `.ui-report__figure` with a
79
+ `.ui-report__caption` and a `.ui-legend` key. The `--chart-value` inline knob
80
+ is gone; the `--chart-color`/`--chart-pattern` swatch knobs remain (legend).
81
+ See `MIGRATIONS.json` (`0.5`→`0.6`) and `docs/vega.md`.
82
+
83
+ ### Changed
84
+
85
+ - **Annotation connectors are crisper.** `connectorEndArrow` now defaults to a
86
+ sharper head (half-angle 0.32 ≈ 37°, size 8 vs the former blunt 0.45 / 7).
87
+ Author-facing geometry only; the `arrowHead` kernel default is unchanged, so
88
+ node-connector arrowheads don't move.
89
+
90
+ ### Accessibility
91
+
92
+ - **Coarse-pointer tap-target floors extended to navigation.** The 2.9 rem
93
+ touch floor (already on primitives/forms/feedback) now also covers
94
+ `.ui-sitenav a`, `.ui-app-nav a`, `.ui-sitemenu > summary`, and
95
+ `.ui-themetoggle__button` under `@media (pointer: coarse)` — the primary nav
96
+ affordances were below the 44 px target on touch.
97
+ - **App shell uses dynamic viewport units.** `100vh` → `100dvh` (shell/body) and
98
+ the scrolling rail → `100svh`, so the rail and its pinned account/footer no
99
+ longer fall under the mobile URL bar.
100
+ - **Forced-colors status dots stay distinct.** `.ui-dot--success/--warning/--danger/--info`
101
+ and `.ui-dotmatrix__cell--hot/--accent` now map to distinct system colors
102
+ under Windows High Contrast instead of collapsing to one — the only signal
103
+ these carry is colour.
104
+ - **Keyboard affordance parity.** `.ui-menu__item:focus-visible` gets the same
105
+ row highlight as hover; the segmented control's focus ring is now inset so the
106
+ container's `overflow: hidden` no longer clips it.
107
+ - **Reduced-motion skeleton.** `.ui-skeleton` flattens to a solid placeholder
108
+ under `prefers-reduced-motion` instead of freezing mid-shimmer.
109
+
110
+ ### Fixed
111
+
112
+ - **Published-type drift (code-quality audit).** `ui.meter({ tone: 'info' })` and
113
+ `ui.bracketNote({ tone: 'success' })` emit real classes at runtime, but the
114
+ generated `.d.ts` tone unions (hand-mirrored in `gen-dts.mjs`) omitted them, so
115
+ a TS consumer got a spurious type error for a value that renders. The unions
116
+ now match the factory; a new `check:recipe-types` gate cross-checks every
117
+ factory's string-literal options against its `*Opts` union so this whole class
118
+ of drift fails CI.
119
+ - **Component-library audit (16-agent dogfood pass) — the validates-but-no-ops
120
+ cluster.** A whole-surface audit found the meter-style trap (a class/token that
121
+ validates and paints but silently does nothing without an undocumented
122
+ precondition) recurring across components. Fixed:
123
+ - `aria-disabled="true"` on `.ui-button` / `.ui-link` now sets
124
+ `pointer-events: none` — it looked dead but a real `<a>` still navigated.
125
+ - Disabled affordance reaches the controls that wrap a native input
126
+ (`.ui-switch` / `.ui-check` / `.ui-segmented__option` via `:has(input:disabled)`,
127
+ plus `.ui-range` / `.ui-file`) — they previously looked operable and their
128
+ label kept `cursor: pointer`.
129
+ - Bare `[aria-current]` selectors (`.ui-sitenav`, `.ui-breadcrumb__item`) now
130
+ scope `:not([aria-current='false'])`, so a correctly-authored
131
+ `aria-current="false"` link is no longer styled as current.
132
+ - The active-tab forced-colors re-assert moved from `base.css` to
133
+ `disclosure.css` (after the default rule) — an earlier bundle leaf let the
134
+ accent default override it, so the selected tab lost its only HC cue.
135
+ - `.ui-meter__fill` / `.ui-progress__bar` get a system colour under
136
+ `forced-colors`, so the measured proportion stays visible.
137
+ - `.ui-search` gains a 2px keyboard focus ring to match every sibling input
138
+ (it had only a 1px border-colour shift).
139
+ - `.ui-prose` gets `overflow-wrap: break-word` — long tokens in
140
+ machine-generated Markdown forced horizontal page scroll.
141
+ - `.ui-mark--draw` is scoped to fill styles (`:not(--underline, --box, --strike)`)
142
+ so it no longer looks applied while doing nothing.
143
+ - `.ui-cq` hardcodes its container-name (the `@container bronto` collapse
144
+ queries hardcode it, so a `--cq-name` override silently killed the collapse).
145
+ - `initPopover()` seeds resting ARIA (`aria-haspopup`, `aria-controls`,
146
+ `aria-expanded`) and syncs `aria-expanded` when the UA closes a native
147
+ popover; `toast()` validates `tone` (an unknown string rendered an unstyled
148
+ neutral toast) and warns; the combobox listbox gets an accessible name.
149
+ - `.ui-error-summary__title` uses the legible sans, not the low-legibility Doto
150
+ display face. `.ui-input` / `.ui-search` autofill stays on-theme.
151
+ - `.ui-reveal` hidden state is gated on `scripting: enabled` (genuinely degrades
152
+ visible with no JS; the prior comment lied) — and `ui-scroll-reveal` is the
153
+ documented zero-JS path.
154
+ - Parity modifiers added: `.ui-meter--info`, `.ui-bracket-note--success`.
155
+ - Responsive/mobile hardening across the framework: `rem`-rooted type for WCAG
156
+ 1.4.4, coarse-pointer tap-target floors, combobox/tour-note viewport clamps,
157
+ and `@media (hover)` gating — with a new responsive e2e sweep.
158
+ - **Faint numbers on stat cards.** `.ui-stat__value` / `.ui-app-metric__value`
159
+ (and the report cover/section titles, rail brand, panel titles, `.ui-display`,
160
+ `.ui-quote`) set the Doto display face but no weight, so they rendered at the
161
+ thinnest cut (400). They now apply `--display-weight(-strong)` — visibly bolder
162
+ and more legible, on screen and in print.
163
+ - **Painted data surfaces dropped in the PDF.** Headless-Chromium print drops
164
+ backgrounds by default, silently blanking the data-bearing fills. Dot-matrix
165
+ cells, the segmented meter, status dots, masked glyphs, highlight marks,
166
+ connector lines, and progress/meter fills now carry `print-color-adjust: exact`
167
+ so they survive the A4 print/PDF that the report kit targets.
168
+ - **Dark-theme cards/tables printed dark-on-white.** The dark→ink token remap was
169
+ scoped to `.ui-report`; it is now lifted to the print `:root` (in the exempt
170
+ token-definition file), so a bare `.ui-card` / `.ui-statgrid` / `.ui-table` —
171
+ the markup an external LLM emits — also prints legibly.
172
+ - Inline `ui-citation` no longer dumps its full URL mid-sentence when printed
173
+ (the reference list carries the URL); `ui-legend--with-values` values are
174
+ right-aligned for a clean tabular column.
175
+ - **Annotation elbow connector was a 45° chamfer, not a dogleg.**
176
+ `connectorElbow` turned by `min(|dx|,|dy|)`, drawing a diagonal stub the
177
+ `stroke-linejoin` bevel never matched. It now delegates to the connectors
178
+ geometry kernel's right-angle `elbowPath` (H/V/H), so an annotation leader and
179
+ a node connector draw the same elbow.
180
+ - **Scoped behaviors no longer hijack the whole document on a null root.**
181
+ `init*({ root })` with an explicitly-provided-but-unready root (a framework
182
+ ref still `null` at mount, a conditional that hasn't rendered) now no-ops
183
+ instead of silently widening to document-wide delegation. The react/solid/qwik
184
+ bindings emit `root: null` for the not-ready case so the distinction survives
185
+ the boundary; passing no `root` still delegates from `document` exactly as
186
+ before. Affects every delegated behavior (dialog, menu, combobox, …).
187
+ - **`--report-width` / `--report-padding-block` are now declared defaults** on
188
+ `.ui-report` — they were read with inline fallbacks but never declared, so the
189
+ override surface was undiscoverable and `--report-measure` looked like the
190
+ width knob when it isn't.
191
+ - Carousel's IntersectionObserver is now set up and torn down in lockstep with
192
+ its event binding, removing a one-tick window where a re-init left two
193
+ observers on the same slides.
194
+ - **`ui-meter` / `ui-progress` fill painted a 0×0 box.** `.ui-meter__fill` and
195
+ `.ui-progress__bar` set `block-size`/`inline-size` but no `display`, so on the
196
+ documented `<span>` fill (an inline box ignores width/height) the bar rendered
197
+ empty — a "validates-but-renders-nothing" trap the registry and docs both
198
+ hid. They are now `display: block`. Found by a second multi-agent dogfood
199
+ pass; guarded going forward by a render-geometry e2e (below).
200
+
201
+ ### Documentation
202
+
203
+ - LLM-authored static reports: a prominent CSS-loading note (bundler vs
204
+ `node_modules` vs CDN) and a copy-pasteable CDN report in
205
+ `docs/reporting.md`; clarified that `dist/bronto.css` does **not** include the
206
+ opt-in report/chart/legend/annotation layers; number/date formatting
207
+ guidance; and a standalone, no-build report reference
208
+ (`demo/report-standalone.html`).
209
+ - Resolved the `is-*` self-contradiction: the framework's own
210
+ `is-num`/`is-pos`/`is-neg`/`is-key`/`is-open` state hooks are valid even
211
+ though they deliberately live outside `cls` (documented in
212
+ `docs/reference.md` and `classes.json`).
213
+ - Clarified two standing contracts in `docs/architecture.md`: `css/analytical.css`
214
+ is the roll-up of exactly the seven figure leaves (annotations, legend, marks,
215
+ connectors, spotlight, crosshair, selection) — `sources`/`state`/`generated`/
216
+ `workbench`/`command` are adjacent leaves imported individually — and the root
217
+ `.` export is CSS-only (no runtime JS at the root). Pre-1.0 stability/pinning
218
+ spelled out in `docs/stability.md`. `docs/workbench.md` notes that
219
+ `.ui-selectionbar` is unrelated to the `.ui-sel--*` selection-emphasis classes.
220
+ - Honest JSDoc limits: combobox/command read options from the DOM at init
221
+ (re-run after replacing them); popover restores focus on Escape but not on
222
+ outside-click; the table sorter is locale-naive display-text; mask-mode glyphs
223
+ are single-tone.
224
+ - **Foreign-renderer recipes hardened after a multi-agent dogfooding pass**
225
+ (build five real reports across the whole stack, review from every POV). The
226
+ Vega CDN recipe now pins the `/build/*.min.js` UMD bundles and `renderer:'svg'`
227
+ (a bare `cdn.jsdelivr.net/npm/vega@6` tag has no `window.vega`, so the previous
228
+ recipe rendered nothing); the file://-portable path (inline the config — an
229
+ imported/fetched config is CORS-blocked from disk) is now explicit. New
230
+ `docs/reporting.md` recipes: "Theming a live report" (the theme-toggle/re-embed
231
+ foot-guns — clear the host, container-width-while-hidden, Mermaid source vs
232
+ output), live charts are `ui-screen-only` while the table prints (a kept live
233
+ chart bakes the on-screen theme), `ui-meter`/`ui-quote` markup, and the
234
+ sequential/diverging frozen-figure ramp. `docs/d2.md` gains a frozen
235
+ inline-`<svg>`-from-slots recipe and on-accent-ink guidance; `docs/vega.md`
236
+ documents the theme-inverting ramp and the OKLCH-vs-d3 gradient-key drift.
237
+ - `docs/annotations.md` states the rule in both directions: a data annotation
238
+ must stay readable (not `aria-hidden`), a decorative one must be hidden.
239
+ - **A second dogfood pass closed the foreign-renderer/contract gaps it found.**
240
+ `docs/sources.md` + `llms.txt` now document the standalone `.ui-src` trust
241
+ pill and state that a `ui-src--*` tone class **needs a host** (a bare
242
+ `<span class="ui-src--verified">` validates but renders nothing), and name the
243
+ source-card body part as `__excerpt` (not `__detail`). `docs/mermaid.md`:
244
+ `gantt`/`timeline` are **not** covered by the base `themeVariables` (they
245
+ render with Mermaid's own defaults — prefer the native `ui-timeline` for a
246
+ report). `docs/mermaid.md` + `docs/d2.md` gain the same `file://` CORS caveat
247
+ Vega carries (inline the map or pre-render). `docs/vega.md`: select the themed
248
+ ramp with `scale: { range: 'heatmap' }` — **not** `scheme:`, which throws — and
249
+ the accent/neutral series map to `--chart-1` / `--chart-8`, so a legend keys
250
+ them with `ui-legend__swatch--1`/`--8` (`docs/legends.md`). `docs/reporting.md`:
251
+ the live-theme recipe now `finalize()`s the prior Vega view before re-embed
252
+ (was leaking a view per toggle), and notes `ui-meter --value` clamps at 100
253
+ (put an over-target figure in the written label). `docs/marks.md`: `ui-mark`
254
+ is a behind-text highlight (contrast-safe; never needs `--on-accent`).
255
+
256
+ ### Internal
257
+
258
+ - **New `check:versions` gate** — every `@ponchia/ui@X.Y.Z` literal in a shipped
259
+ doc (`llms.txt`, `docs/reporting.md`, …) must equal `package.json`, so a stale
260
+ CDN pin can't ship to LLM/copy-paste consumers on the next bump.
261
+ - **Dev-dependency Vega bumped to the v6 stack** — the render-probe now runs on
262
+ `vega@^6.2.0` + `vega-lite@^6.4.3` (Vega-Lite 6 peers Vega 6; a Vega-Lite-6 ÷
263
+ Vega-5 mix is incoherent). The theme `config` is version-independent resolved
264
+ hex, so the artifacts and the probe assertions are unchanged; the documented
265
+ CDN recipe is re-pinned to the matching majors (`vega@6.2.0` / `vega-lite@6.4.3`
266
+ / `vega-embed@7.1.0`, all still shipping a UMD `/build/*.min.js`). Vega remains
267
+ the consumer's renderer, not a runtime dependency.
268
+ - **New `check:doc-recipes` gate** — a `<script src>` CDN recipe in a shipped doc
269
+ must pin a jsDelivr `/build/*.min.js` UMD bundle, never a bare
270
+ `cdn.jsdelivr.net/npm/<pkg>@N` redirect (which serves a module bundle with no
271
+ global and renders nothing). Docs are otherwise an untested surface; this is
272
+ the structural guard that closes the broken-recipe class the dogfood pass
273
+ found. `<link href>` CSS and prose mentions are exempt.
274
+ - **`classes.json` `customProperties` expanded** to cover the load-bearing,
275
+ no-op-without-it knobs the audit found undocumented: the **required**
276
+ `--icon-mask` (a bare `.ui-icon` paints a solid square without it) and
277
+ `--ui-vt-name` (`.ui-vt` is inert without it), plus `--icon-size`. The
278
+ `states` manifest comment now explicitly names the runtime-managed hooks it
279
+ deliberately excludes (`is-leaving`/`is-visible`/`is-in`/`is-on`) so the
280
+ omission reads as intentional, not a gap. `--on-accent` is annotated at its
281
+ token source as a read-only export for foreign renderers (in-DOM ink is
282
+ `--button-text`). `contrast.md` now prints APCA `Lc` to one decimal so an
283
+ advisory shortfall (e.g. `Lc 44.9`) no longer rounds to a passing-looking `45`.
284
+ - Raw bundle budget 81 → 82 kB for the component-audit accessibility/state
285
+ blocks (gzip held ~14.1 kB — the additions are repetitive media-query and
286
+ `:has()`/`:not()` rules that compress well).
287
+ - **Code-quality audit (16-agent) — two new gates + targeted dedup, no churn.**
288
+ A code-health pass (complexity / duplication / AI-slop / missing-best-practice)
289
+ that deliberately left working, gate-protected code alone. Added:
290
+ `check:recipe-types` (factory↔`.d.ts` option parity, above) and `check:chain`
291
+ (every `check:*` script is wired into the aggregate `check` chain — closes the
292
+ silent-coverage-drop class; it would have caught a forgotten gate). Reconciled
293
+ a latent bug — `clamp()` had silently diverged between `connectors` and
294
+ `annotations`; the two now share one scalar/geometry kernel (the guarded form).
295
+ Dedup that removed real duplication: a shared `collectHosts()` /
296
+ `scrollIntoViewSafe()` / `wrapIndex()` in `behaviors/internal.js` (~9 behaviors),
297
+ a `freshnessErrors()` helper reused by 7 drift gates, the shared `CSS_COLOR`
298
+ regex across the 3 foreign-renderer gates, `check-report`'s opt-in list as a
299
+ loop, `check-pack`'s shipped-docs derived from `pkg.files`, and a looser
300
+ `check-classes` recipe-scrape. README hero de-densified; `srcTone` matched to
301
+ `stateTone`'s idiom; the intentional badge accent-mix (45% vs 40%) documented.
302
+ - **`check:dist` now asserts source-coverage** — every `css/*.css` leaf must be
303
+ bundled, an opt-in `EXTRA_LEAVES` entry, or a roll-up; an orphaned leaf that
304
+ would ship nothing now fails loudly (the inverse of the existing stale-dist
305
+ guard).
306
+ - **`check:dts-emit` now compares `.d.ts.map`** mapping data (volatile `sources`
307
+ path normalized), closing a drift hole the code comment had acknowledged.
308
+ - DTCG export types `--display-weight*` as the spec `fontWeight` type (was
309
+ `number`). Corrected stale `check-tokens.mjs` doc references (the real gate is
310
+ `check:fresh`).
311
+ - Tests: binding hook-surface parity is now **derived** from the modules (the old
312
+ hard-coded list silently omitted the five analytical hooks); a new
313
+ `analytical-boundary` test makes the "no scales/state/fetch/global-hotkey"
314
+ contract executable; a new behavior test pins the null-root no-op.
315
+ - Removed four dead keyframes (`scan`/`growBar`/`drawLine`/`pulseNode`) from
316
+ `motion.css`. Raw bundle budget 80 → 81 kB for the accessibility blocks (gzip
317
+ held ~14.0 kB).
318
+ - **`classes.json` `--value` retargeted** to `.ui-meter__fill, .ui-progress__bar`
319
+ (was the `.ui-meter, .ui-progress` track parent) — the custom property is read
320
+ on the fill child, so the machine-readable manifest now matches where an author
321
+ actually sets it.
322
+ - **New render-geometry e2e** (`test/e2e/render-geometry.spec.mjs`) — launches a
323
+ browser at the demo's real report primitives and asserts the `.ui-meter__fill`
324
+ / `.ui-progress__bar` fills and the standalone `.ui-src` pill paint a non-zero
325
+ box (via `getBoundingClientRect`, not the inline-box-lying
326
+ `getComputedStyle().inlineSize`). Closes the validates-but-renders-nothing
327
+ category that hid the meter regression. The demo gains a standalone `.ui-src`
328
+ pill row to exercise it.
329
+
8
330
  ## 0.5.0 — 2026-06-02
9
331
 
10
332
  A **minor** that builds out the "analytical & generated-report UI" identity: a
package/MIGRATIONS.json CHANGED
@@ -87,6 +87,20 @@
87
87
  }
88
88
  ],
89
89
  "codemod": "rg -l 'ui-chart__legend|ui-chart__swatch' then s/ui-chart__swatch/ui-legend__swatch/g and rework the ul.ui-chart__legend wrapper into ul.ui-legend with li.ui-legend__item rows. See docs/legends.md."
90
+ },
91
+ {
92
+ "from": "0.5",
93
+ "to": "0.6",
94
+ "summary": "Charting realignment. The local static bar-chart renderer (.ui-chart*) is removed — a chart needs scales + data binding, out of scope for the analytical layer. bronto is now a themeable target for Vega-Lite (@ponchia/ui/vega), the same tokens-as-data path as Mermaid/D2. The --chart-* data-viz palette, tokens/charts.json, and the .ui-legend layer are unchanged.",
95
+ "safe": [],
96
+ "manual": [
97
+ {
98
+ "old": "ui-chart / ui-chart__plot / ui-chart__bar / ui-chart__label / ui-chart__track / ui-chart__fill / ui-chart__fallback / ui-chart__caption",
99
+ "new": "a Vega-Lite chart themed with @ponchia/ui/vega, or a token-themed inline <svg>",
100
+ "note": "No 1:1 class mapping — the renderer is removed. For a real chart: import '@ponchia/ui/vega', pass brontoVegaConfig(theme) to vega-embed, and place the result in a <figure class=\"ui-report__figure\"> with a <figcaption class=\"ui-report__caption\"> and a <ul class=\"ui-legend\"> key (see docs/vega.md). For a frozen/print chart: hand-author an inline <svg> using the --chart-N palette tokens for fills. The --chart-value inline knob is gone; --chart-color/--chart-pattern remain on .ui-legend__swatch."
101
+ }
102
+ ],
103
+ "codemod": "No codemod — the .ui-chart* renderer has no replacement class. rg -l 'ui-chart\\\\b|ui-chart__' to find call sites, then rebuild each as a Vega-Lite chart (@ponchia/ui/vega) or a token-themed inline <svg>. See docs/vega.md."
90
104
  }
91
105
  ]
92
106
  }
package/README.md CHANGED
@@ -8,7 +8,19 @@
8
8
  [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Ponchia/bronto-ui/badge)](https://scorecard.dev/viewer/?uri=github.com/Ponchia/bronto-ui)
9
9
  [![license: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/Ponchia/bronto-ui/blob/main/LICENSE)
10
10
 
11
- **A CSS-first design system for interfaces that explain themselves.** Works in plain HTML, every modern framework, and print/PDF — there's no component runtime to adopt. The look is a deliberate stance: a neutral monochrome canvas with **one _rationed_ accent** (colour _signals_, it never decorates), dot-matrix display type and hairline borders, re-skinnable from a single `--accent` knob (opt-in amber-CRT · phosphor-green · e-ink colorways). And beyond the standard component set it ships an opt-in **analytical & report layer** — SVG annotations, legends, leader-line connectors, a guided-focus spotlight, text marks, a colourblind-safe data-viz palette and a static/PDF report grammar — for dashboards and LLM-authored reports. Zero runtime dependencies; re-brand the whole thing with one CSS variable.
11
+ **A CSS-first design system for interfaces that explain themselves.** It works in
12
+ plain HTML, every modern framework, and print/PDF, with no component runtime to
13
+ adopt and zero runtime dependencies.
14
+
15
+ The look is a deliberate stance: a neutral monochrome canvas with one rationed
16
+ accent (colour signals, it never decorates), dot-matrix display type, and
17
+ hairline borders — all re-skinnable from a single `--accent` knob (opt-in
18
+ amber-CRT, phosphor-green, and e-ink colorways).
19
+
20
+ Beyond the standard component set it ships an opt-in analytical & report layer —
21
+ SVG annotations, legends, leader-line connectors, a guided-focus spotlight, text
22
+ marks, a colourblind-safe data-viz palette, and a static/PDF report grammar — for
23
+ dashboards and LLM-authored reports.
12
24
 
13
25
  ### [Live demo →](https://ponchia.github.io/bronto-ui/) &nbsp;·&nbsp; [Theme playground →](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)
14
26
 
@@ -18,7 +30,16 @@ The demo is the kitchen sink — every component, light/dark, RTL, live theming.
18
30
 
19
31
  ## What it is
20
32
 
21
- `@ponchia/ui` ships its design as **CSS**, not components. You drop in one stylesheet and style with semantic `ui-*` classes; an optional thin layer of typed class-name recipes and SSR-safe vanilla behaviors sits on top for the few things that genuinely need JS (theme persistence, dialogs, toasts, disclosure). The guiding principle is **color is rationed, structure carries meaning** — layout, type weight and the hairline do the work before a hue does, and the accent is a spotlight, not a paint bucket. Because everything lives in a single `@layer bronto`, your own un-layered CSS overrides the framework with no specificity fight and no `!important`.
33
+ `@ponchia/ui` ships its design as CSS, not components. You drop in one stylesheet
34
+ and style with semantic `ui-*` classes; an optional thin layer of typed
35
+ class-name recipes and SSR-safe vanilla behaviors sits on top for the few things
36
+ that genuinely need JS (theme persistence, dialogs, toasts, disclosure).
37
+
38
+ The guiding principle is that **colour is rationed and structure carries
39
+ meaning** — layout, type weight, and the hairline do the work before a hue does,
40
+ and the accent is a spotlight, not a paint bucket. Because everything lives in a
41
+ single `@layer bronto`, your own un-layered CSS overrides the framework with no
42
+ specificity fight and no `!important`.
22
43
 
23
44
  It ships a complete, accessible **standard component set** — but that's not where it competes. Its differentiator is an opt-in **analytical & communication layer** for interfaces that make complex work legible: annotations, legends, connectors, marks, a guided-focus spotlight, lifecycle/system-state and source-provenance vocabularies, and a static/PDF report grammar. Each owns only its visual grammar and pure geometry — no chart engine, no state, no hit-testing. See **[docs/frontier-primitives.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/frontier-primitives.md)** for the thesis.
24
45
 
@@ -36,7 +57,7 @@ Or drop it in with no build step, straight from a CDN:
36
57
 
37
58
  ## Quick start
38
59
 
39
- **1. Load the CSS.** One flattened, minified bundle — the whole framework, one request (~76 kB raw / ~13 kB gzip):
60
+ **1. Load the CSS.** One flattened, minified bundle — the whole standard component set, one request (~76 kB raw / ~13 kB gzip):
40
61
 
41
62
  ```css
42
63
  @import '@ponchia/ui'; /* via a bundler */
@@ -49,6 +70,8 @@ Or drop it in with no build step, straight from a CDN:
49
70
 
50
71
  > Prefer source leaves through a bundler? Use `@import '@ponchia/ui/css'` (a thin `@import` fan-out) instead. Both resolve the Doto `@font-face` with relative URLs, so there's no `/fonts` path assumption.
51
72
 
73
+ > The bundle is the standard component set. The opt-in analytical & report layers — `report.css`, `dataviz.css`, `annotations.css`, `legend.css`, and the rest — are **not** in `bronto.css`; link each one you need from `dist/css/`. For LLM-authored static reports see [docs/reporting.md](docs/reporting.md).
74
+
52
75
  **2. Write markup with `ui-*` classes** (primary is the default button; modifiers are opt-in):
53
76
 
54
77
  ```html
@@ -168,7 +191,7 @@ Recent-evergreen, by design. The framework targets the modern web platform — c
168
191
 
169
192
  ## Versioning
170
193
 
171
- Pre-1.0 and deliberately so. **Until `1.0.0`, breaking changes ship in the _minor_** (`0.x.0`); patches (`0.x.y`) are always non-breaking. Pin with the patch range — at `0.x`, `~0.5.0` (and equivalently `^0.5.0`) resolves to `>=0.5.0 <0.6.0`, giving you safe patches while holding back the next breaking minor. Every breaking change is called out under a **BREAKING** heading in the **[CHANGELOG](https://github.com/Ponchia/bronto-ui/blob/main/CHANGELOG.md)** with a migration note.
194
+ Pre-1.0 and deliberately so. **Until `1.0.0`, breaking changes ship in the _minor_** (`0.x.0`); patches (`0.x.y`) are always non-breaking. Pin with the patch range — at `0.x`, `~0.6.0` (and equivalently `^0.6.0`) resolves to `>=0.6.0 <0.7.0`, giving you safe patches while holding back the next breaking minor. Every breaking change is called out under a **BREAKING** heading in the **[CHANGELOG](https://github.com/Ponchia/bronto-ui/blob/main/CHANGELOG.md)** with a migration note.
172
195
 
173
196
  Contractual (changes are breaking): token **names** and documented token roles, `.ui-*` class and recipe names, `data-bronto-*` attributes, exported behavior/glyph/binding function names and each behavior's cleanup contract. Not contractual (may change any release): exact token **values** and generated colour math outputs (visual tuning) unless a doc explicitly says the value is stable, plus internal leaf-file / `@layer` boundaries. See **[docs/stability.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/stability.md)** for the full public-surface matrix.
174
197
 
@@ -178,7 +201,7 @@ Release candidates publish to the `next` dist-tag, never to `latest` — opt in
178
201
 
179
202
  - **[Live demo](https://ponchia.github.io/bronto-ui/)** · **[Theme playground](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)**
180
203
  - **[Class reference](https://github.com/Ponchia/bronto-ui/blob/main/docs/reference.md)** · **[Usage guide](https://github.com/Ponchia/bronto-ui/blob/main/docs/usage.md)** · **[Theming](https://github.com/Ponchia/bronto-ui/blob/main/docs/theming.md)** · **[Contrast](https://github.com/Ponchia/bronto-ui/blob/main/docs/contrast.md)** · **[Color system (ADR-0001)](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0001-color-system.md)** · **[Scope & 2026 baseline (ADR-0002)](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0002-scope-and-2026-baseline.md)**
181
- - **[CHANGELOG](https://github.com/Ponchia/bronto-ui/blob/main/CHANGELOG.md)** · **[Roadmap](https://github.com/Ponchia/bronto-ui/blob/main/ROADMAP.md)** · **[Contributing](https://github.com/Ponchia/bronto-ui/blob/main/CONTRIBUTING.md)**
204
+ - **[CHANGELOG](https://github.com/Ponchia/bronto-ui/blob/main/CHANGELOG.md)** · **[Roadmap](https://github.com/Ponchia/bronto-ui/blob/main/ROADMAP.md)** · **[Contributing](https://github.com/Ponchia/bronto-ui/blob/main/CONTRIBUTING.md)** · **[Repository layout](https://github.com/Ponchia/bronto-ui/blob/main/docs/architecture.md#repository-layout)**
182
205
 
183
206
  ## License
184
207