@ponchia/ui 0.4.1 → 0.5.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 (105) hide show
  1. package/CHANGELOG.md +230 -8
  2. package/MIGRATIONS.json +92 -0
  3. package/README.md +9 -6
  4. package/annotations/index.d.ts +280 -0
  5. package/annotations/index.js +522 -0
  6. package/behaviors/carousel.js +197 -0
  7. package/behaviors/combobox.js +195 -0
  8. package/behaviors/command.js +187 -0
  9. package/behaviors/connectors.js +96 -0
  10. package/behaviors/crosshair.js +58 -0
  11. package/behaviors/dialog.js +73 -0
  12. package/behaviors/disclosure.js +25 -0
  13. package/behaviors/dismissible.js +24 -0
  14. package/behaviors/forms.js +158 -0
  15. package/behaviors/glyph.js +109 -0
  16. package/behaviors/index.d.ts +79 -0
  17. package/behaviors/index.js +18 -1409
  18. package/behaviors/internal.js +50 -0
  19. package/behaviors/legend.js +46 -0
  20. package/behaviors/menu.js +46 -0
  21. package/behaviors/popover.js +108 -0
  22. package/behaviors/spotlight.js +53 -0
  23. package/behaviors/table.js +109 -0
  24. package/behaviors/tabs.js +103 -0
  25. package/behaviors/theme.js +82 -0
  26. package/behaviors/toast.js +152 -0
  27. package/classes/index.d.ts +280 -2
  28. package/classes/index.js +313 -2
  29. package/connectors/index.d.ts +71 -0
  30. package/connectors/index.js +179 -0
  31. package/css/analytical.css +21 -0
  32. package/css/annotations.css +292 -0
  33. package/css/command.css +97 -0
  34. package/css/connectors.css +93 -0
  35. package/css/crosshair.css +100 -0
  36. package/css/feedback.css +51 -0
  37. package/css/fonts.css +11 -7
  38. package/css/generated.css +117 -0
  39. package/css/legend.css +268 -0
  40. package/css/marks.css +144 -0
  41. package/css/primitives.css +18 -0
  42. package/css/report.css +12 -31
  43. package/css/selection.css +46 -0
  44. package/css/sources.css +179 -0
  45. package/css/spotlight.css +104 -0
  46. package/css/state.css +121 -0
  47. package/css/tokens.css +25 -37
  48. package/css/workbench.css +83 -0
  49. package/dist/bronto.css +1 -1
  50. package/dist/css/analytical.css +1 -0
  51. package/dist/css/annotations.css +1 -0
  52. package/dist/css/command.css +1 -0
  53. package/dist/css/connectors.css +1 -0
  54. package/dist/css/crosshair.css +1 -0
  55. package/dist/css/feedback.css +1 -1
  56. package/dist/css/fonts.css +1 -1
  57. package/dist/css/generated.css +1 -0
  58. package/dist/css/legend.css +1 -0
  59. package/dist/css/marks.css +1 -0
  60. package/dist/css/primitives.css +1 -1
  61. package/dist/css/report.css +1 -1
  62. package/dist/css/selection.css +1 -0
  63. package/dist/css/sources.css +1 -0
  64. package/dist/css/spotlight.css +1 -0
  65. package/dist/css/state.css +1 -0
  66. package/dist/css/workbench.css +1 -0
  67. package/docs/adr/0003-theme-model.md +7 -4
  68. package/docs/annotations.md +345 -0
  69. package/docs/architecture.md +202 -0
  70. package/docs/command.md +95 -0
  71. package/docs/connectors.md +91 -0
  72. package/docs/crosshair.md +63 -0
  73. package/docs/generated.md +91 -0
  74. package/docs/legends.md +168 -0
  75. package/docs/marks.md +86 -0
  76. package/docs/reference.md +309 -3
  77. package/docs/reporting.md +49 -14
  78. package/docs/selection.md +40 -0
  79. package/docs/sources.md +110 -0
  80. package/docs/spotlight.md +78 -0
  81. package/docs/stability.md +16 -1
  82. package/docs/state.md +85 -0
  83. package/docs/usage.md +22 -0
  84. package/docs/workbench.md +72 -0
  85. package/fonts/doto-400.woff2 +0 -0
  86. package/fonts/doto-500.woff2 +0 -0
  87. package/fonts/doto-600.woff2 +0 -0
  88. package/fonts/doto-700.woff2 +0 -0
  89. package/fonts/doto-800.woff2 +0 -0
  90. package/fonts/doto-900.woff2 +0 -0
  91. package/llms.txt +229 -6
  92. package/package.json +69 -4
  93. package/qwik/index.d.ts +5 -0
  94. package/qwik/index.js +20 -0
  95. package/react/index.d.ts +5 -0
  96. package/react/index.js +10 -0
  97. package/solid/index.d.ts +5 -0
  98. package/solid/index.js +10 -0
  99. package/tokens/index.js +9 -5
  100. package/fonts/doto-400.ttf +0 -0
  101. package/fonts/doto-500.ttf +0 -0
  102. package/fonts/doto-600.ttf +0 -0
  103. package/fonts/doto-700.ttf +0 -0
  104. package/fonts/doto-800.ttf +0 -0
  105. package/fonts/doto-900.ttf +0 -0
package/CHANGELOG.md CHANGED
@@ -1,9 +1,234 @@
1
1
  # Changelog
2
2
 
3
- > **Versioning:** pre-1.0, breaking changes ship in the _minor_. Pin
4
- > `~0.x`; `^0.x` does **not** protect you. See README → Versioning, and
3
+ > **Versioning:** pre-1.0, breaking changes ship in the _minor_. Pin to the
4
+ > minor — `~0.4.0` (equivalently `^0.4.0`) resolves to `>=0.4.0 <0.5.0`; a bare
5
+ > `^0` / `*` wildcard does **not** protect you. See README → Versioning, and
5
6
  > the deprecation policy in CONTRIBUTING.md.
6
7
 
8
+ ## 0.5.0 — 2026-06-02
9
+
10
+ A **minor** that builds out the "analytical & generated-report UI" identity: a
11
+ full suite of opt-in **communication primitives** — SVG annotations, legends,
12
+ text/evidence marks, leader-line connectors, a guided-focus spotlight, a
13
+ crosshair/readout, a selection-state vocabulary, label declutter + direct labels
14
+ (`declutterLabels`/`directLabels`), and a source/citation/provenance **trust
15
+ layer** — plus a consolidation pass over them. Each owns its visual grammar and
16
+ pure geometry and refuses to own scales/state/hit-testing (no chart engine).
17
+
18
+ Per the project's versioning policy, breaking changes ship in the minor. This
19
+ release carries three: the opt-in report kit's chart data key moved into the new
20
+ legend layer (`.ui-chart__legend`/`__swatch` removed — see Changed and
21
+ [`MIGRATIONS.json`](MIGRATIONS.json)), annotation arrowheads now render via
22
+ the shared connectors geometry kernel (a small path-shape change), and the
23
+ opt-in marks' rationed-accent tone was renamed `evidence`→`accent` to match the
24
+ rest of the analytical tone vocabulary. Everything else is additive and opt-in,
25
+ save for the tiny `.ui-shortcut` keyboard-hint primitive that joins the core
26
+ layer; the rest of the default `dist/bronto.css` is unchanged. Also folds in the
27
+ 0.4.x maintenance hardening that had not yet been released.
28
+
29
+ ### Added
30
+
31
+ - **SVG annotations** (`@ponchia/ui/css/annotations.css`,
32
+ `@ponchia/ui/annotations`, `.ui-annotation*`, `ui.annotation()`): an opt-in
33
+ annotation layer for charts, reports, and analytical figures, following the
34
+ d3-annotation grammar (a **subject** marks the thing, a **connector** points
35
+ away, a **note** carries the text). Ships a class grammar (variants for
36
+ label/callout/elbow/curve/circle/rect/threshold/badge/bracket/band/slope/
37
+ compare/cluster/axis/timeline/evidence, six tones, and opt-in
38
+ `draw`/`reveal`/`pulse`/`focus` motion that respects `prefers-reduced-motion`)
39
+ plus tiny geometry helpers that return SVG strings only — they own no chart
40
+ scales, mutate no DOM, and provide no edit mode. Documented in
41
+ [`docs/annotations.md`](docs/annotations.md) and gated by `check:report`.
42
+ - **Legends / data keys** (`@ponchia/ui/css/legend.css`, `.ui-legend*`,
43
+ `ui.legend()`/`ui.legendItem()`/`ui.legendSwatch()`, `initLegend`): an opt-in,
44
+ standalone data-key layer that reads the `--chart-*` palette tokens.
45
+ Categorical, continuous gradient (sequential + `--diverging`), threshold, and
46
+ pattern keys; swatch colour set inline (`--chart-color`) or via
47
+ `.ui-legend__swatch--1..8` index helpers; vertical/compact/with-values
48
+ layouts. WCAG 1.4.1 by construction (the text label is the non-colour
49
+ channel), with `forced-colors` and print care. Optional interactive
50
+ (series-toggling) entries are `<button aria-pressed>` controls: `initLegend`
51
+ flips `aria-pressed`/`.is-inactive` and emits `bronto:legend:toggle`
52
+ (`{ series, active }`) — the host owns hiding the series and any `aria-live`
53
+ announcement (it is never a chart engine). Optional `useLegend` hook in the
54
+ React/Solid/Qwik bindings. New `check:legend` gate proves swatch colours are a
55
+ subset of `tokens/charts.js` and never a raw hex. Documented in
56
+ [`docs/legends.md`](docs/legends.md).
57
+ - **Text marks / evidence** (`@ponchia/ui/css/marks.css`, `.ui-mark*`,
58
+ `.ui-bracket-note*`, `ui.mark()`/`ui.bracketNote()`): an opt-in layer of
59
+ sober, report-grade emphasis for running prose — the counterpart to SVG
60
+ annotations (annotations call out a figure, marks call out a sentence). Inline
61
+ `.ui-mark` (highlight/underline/box/strike; `--accent` + status
62
+ tones; `--draw` reduced-motion-safe sweep) for use on `<mark>`, and
63
+ `.ui-bracket-note` for bracketing a whole passage. Pure CSS on semantic
64
+ tokens, monochrome by default, with `forced-colors` care. Documented in
65
+ [`docs/marks.md`](docs/marks.md).
66
+ - **Connectors / leader lines** (`@ponchia/ui/css/connectors.css`,
67
+ `@ponchia/ui/connectors`, `.ui-connector*`, `initConnectors`, `ui.connector()`):
68
+ an opt-in layer that draws a line between two DOM elements (the
69
+ page-coordinate cousin of annotations). Pure geometry helpers
70
+ (`connectRects`/`connectorPath`/`arrowHead`/…) that return SVG strings and own
71
+ no DOM, an `.ui-connector` overlay grammar (straight/elbow/curve, arrow/dot
72
+ ends, tones, dashed, `--draw`), and an optional `initConnectors` behavior that
73
+ draws + tracks on resize/scroll. `useConnectors` in the bindings. Documented in
74
+ [`docs/connectors.md`](docs/connectors.md).
75
+ - **Spotlight / guided focus** (`@ponchia/ui/css/spotlight.css`, `.ui-spotlight*`,
76
+ `.ui-tour-note*`, `initSpotlight`, `ui.spotlight()`): an opt-in guided-focus
77
+ overlay — a box-shadow cutout over a target element, optional ring, and a
78
+ callout note. `initSpotlight` positions the cutout (`--spot-x/y/w/h`) and
79
+ re-places on resize/scroll and when `data-target` changes. Deliberately **not**
80
+ a tour engine — the host owns step order/advancing/visibility. `useSpotlight`
81
+ in the bindings. Documented in [`docs/spotlight.md`](docs/spotlight.md).
82
+ - **Crosshair / readout** (`@ponchia/ui/css/crosshair.css`, `.ui-crosshair*`,
83
+ `.ui-readout`, `initCrosshair`, `ui.crosshair()`): an opt-in plot ruler +
84
+ pinned readout. `initCrosshair` tracks the pointer over a
85
+ `[data-bronto-crosshair]` plot, sets `--crosshair-x/y`, and dispatches
86
+ `bronto:crosshair:move` with px + 0–1 fractions — it reports position only and
87
+ never maps pixels to data (that needs the host's scales). `useCrosshair` in the
88
+ bindings. Documented in [`docs/crosshair.md`](docs/crosshair.md).
89
+ - **Selection states** (`@ponchia/ui/css/selection.css`, `.ui-sel*`,
90
+ `ui.sel()`): a tiny cross-cutting selection-emphasis vocabulary
91
+ (`--on`/`--off`/`--maybe`) reusable on chart marks, table rows, list items, or
92
+ map regions. The carve-out from brush/lasso — Bronto styles the states; the
93
+ host owns the selection/hit-test logic. Documented in
94
+ [`docs/selection.md`](docs/selection.md).
95
+ - **Sources, citations & provenance** (`@ponchia/ui/css/sources.css`,
96
+ `.ui-citation`/`.ui-source-card`/`.ui-source-list`/`.ui-provenance`,
97
+ `ui.citation()`/`ui.source()`/`ui.provenance()`): an opt-in, CSS-only **trust
98
+ layer** for generated reports and AI output — the grammar for "where did this
99
+ come from?". A cross-cutting `.ui-src--*` state (verified/reviewed/generated/
100
+ unverified/stale/conflict) sets a rationed tone, always paired with an
101
+ author-written label (never colour alone). Bronto owns the grammar + states;
102
+ the host owns fetching, citation numbering, and trust. The first
103
+ frontier-primitive beyond the analytical suite. Documented in
104
+ [`docs/sources.md`](docs/sources.md).
105
+ - **Keyboard-shortcut hint** (`.ui-shortcut` + `.ui-shortcut__sep`, core): a tiny
106
+ universal-chrome primitive that lays out one or more `.ui-kbd` keys as a chord
107
+ (`⌘`+`K`) or sequence (`G` then `I`) with a dim connective. The command tier's
108
+ smallest piece, broadly useful outside a palette (menu items, buttons,
109
+ tooltips). Class-only, like `.ui-kbd`.
110
+ - **Lifecycle / system state** (`@ponchia/ui/css/state.css`, `.ui-state`
111
+ (+`__label`/`__detail`/`--busy`) with canonical state modifiers
112
+ (saving/saved/queued/offline/stale/conflict/error/locked/reviewed/
113
+ needs-review), `.ui-syncbar`, `ui.state()`): an opt-in, CSS-only vocabulary for
114
+ the states apps actually live in — a labelled state object with a rationed tone
115
+ and a page/document sync bar. The label is the state (never colour alone);
116
+ `--busy` pulses the indicator (reduced-motion-safe). Bronto ships the visual
117
+ states + canonical wording; the host owns the state machine, retry, and
118
+ persistence. Frontier candidate #2. Documented in [`docs/state.md`](docs/state.md).
119
+ - **Generated content & AI trust** (`@ponchia/ui/css/generated.css`,
120
+ `.ui-generated`/`.ui-origin-label`/`.ui-reasoning`/`.ui-tool-log`/`.ui-tool-call`,
121
+ `ui.originLabel()`): an opt-in, CSS-only set of **trust surfaces** for AI /
122
+ system-generated content — a marked region, an origin label, and quiet
123
+ native-`<details>` reasoning + tool-call logs. Not a chat kit; no
124
+ fabricated-confidence widget. Bronto styles disclosure/origin/trace, the host
125
+ owns model metadata, redaction, and safety. Pairs with the source layer.
126
+ Documented in [`docs/generated.md`](docs/generated.md).
127
+ - **Workbench** (`@ponchia/ui/css/workbench.css`, `.ui-inspector`/`.ui-property`/
128
+ `.ui-selectionbar`): an opt-in, CSS-only core for tool UIs — a selected-object
129
+ inspector panel, denser property rows, and a raised selection action bar.
130
+ Layout + affordances only; resizable split panes and drag handles are
131
+ deferred. Documented in [`docs/workbench.md`](docs/workbench.md).
132
+ - **Command palette** (`@ponchia/ui/css/command.css`, `.ui-command` (+
133
+ `__input`/`__list`/`__group`/`__item`/`__shortcut`/`__meta`/`__empty`),
134
+ `initCommand`, `useCommand`): an opt-in CSS shell + behavior — filter +
135
+ keyboard-navigate a DOM-authored command list (roving focus, group hiding,
136
+ full keyboard), emitting `bronto:command:select` ({ value, label }) and
137
+ `bronto:command:close`. Bronto navigates; the host owns the action registry,
138
+ routing, and execution. No global Cmd/Ctrl+K. Completes the command tier
139
+ (frontier #3) atop the shipped `ui-shortcut`. Documented in
140
+ [`docs/command.md`](docs/command.md).
141
+ - **Label declutter** (`@ponchia/ui/annotations` `declutterLabels`): a
142
+ deterministic, order-preserving **1-D** label de-overlap helper (sort, push
143
+ apart by `size + gap`, slide to fit `max`) — pure, no DOM/scales. Not a 2-D
144
+ collision solver. Documented in [`docs/annotations.md`](docs/annotations.md).
145
+ - **Direct labels** (`@ponchia/ui/annotations` `directLabels`): the
146
+ direct-labeling companion to `declutterLabels` — it declutters labels along an
147
+ axis **and** draws the leader from each anchor to its placed label, reusing the
148
+ connectors geometry kernel. Returns `[{ x, y, anchor, key, d }]` (the `d` feeds
149
+ a `ui-annotation__connector`). Deterministic and pure: no scales, no DOM, no
150
+ 2-D placement (the 1-D core of Labella, completed with leaders). Documented in
151
+ [`docs/annotations.md`](docs/annotations.md).
152
+ - **Connectors** (`@ponchia/ui/connectors`, `@ponchia/ui/css/connectors.css`,
153
+ `initConnectors`, `useConnectors`, `ui.connector()`) and **Spotlight**
154
+ (`css/spotlight.css`, `initSpotlight`, `ui.spotlight()`) — leader lines between
155
+ DOM elements and a guided-focus overlay; both opt-in, geometry/visual only
156
+ (the host owns layout/tour state).
157
+ - **Crosshair / readout** (`css/crosshair.css`, `initCrosshair`,
158
+ `ui.crosshair()`) and **selection states** (`css/selection.css`, `ui.sel()`) —
159
+ a plot ruler that reports pointer position (not data), and a cross-cutting
160
+ `.ui-sel--on/off/maybe` emphasis vocabulary (the host owns brush/hit-test).
161
+ - **`@ponchia/ui/css/analytical.css`** — a convenience roll-up that bundles the
162
+ seven analytical leaves (annotations, legend, marks, connectors, spotlight,
163
+ crosshair, selection) into one import. Add `dataviz.css`/`report.css`
164
+ separately as needed.
165
+
166
+ ### Fixed
167
+
168
+ - The optional Qwik binding (`@ponchia/ui/qwik`) is now built from the packed
169
+ tarball in CI **and** release, alongside React/Solid — closing a coverage gap
170
+ (it was documented as optimizer-proven but no job actually built it). Also
171
+ covered by `check:pack`, the size report, and the dead-code config.
172
+
173
+ ### Changed
174
+
175
+ - **Breaking (opt-in report kit):** the chart data key moved out of
176
+ `css/report.css` into the standalone `css/legend.css`. `.ui-chart__legend` →
177
+ `.ui-legend` (now with `.ui-legend__item`/`.ui-legend__label` rows) and
178
+ `.ui-chart__swatch` → `.ui-legend__swatch`. Import `@ponchia/ui/css/legend.css`
179
+ beside the report kit; see [`MIGRATIONS.json`](MIGRATIONS.json) and
180
+ [`docs/legends.md`](docs/legends.md). The `--chart-color`/`--chart-pattern`
181
+ swatch contract is unchanged, so the rename is mechanical.
182
+ - **Breaking (opt-in marks):** the rationed-accent **tone** on `.ui-mark` and
183
+ `.ui-bracket-note` was renamed `evidence` → `accent` (`ui-mark--evidence` →
184
+ `ui-mark--accent`, `ui-bracket-note--evidence` → `ui-bracket-note--accent`;
185
+ `ui.mark({ tone: 'accent' })` / `ui.bracketNote({ tone: 'accent' })`) so the
186
+ accent tone reads the same across every analytical primitive (it already was
187
+ `accent` on `ui.connector`/`ui.annotation`). `.ui-annotation--evidence` is
188
+ **unchanged** — it is a marker _variant_ (a proof/source shape), not a tone.
189
+ Mechanical whole-token rename; see [`MIGRATIONS.json`](MIGRATIONS.json).
190
+ - **Consolidation:** the SVG geometry is single-sourced in the `connectors`
191
+ kernel — `@ponchia/ui/annotations` now builds its connectors on it, so a
192
+ line/curve/arrow/dot is drawn one way across both. `connectorLine`/`Curve`/
193
+ `EndDot` output is byte-identical; **`connectorEndArrow` is the one
194
+ (minor-breaking) shape change** — the arrowhead now matches the connectors
195
+ arrowhead. New `check:helpers-dts` gate keeps the hand-maintained
196
+ `annotations`/`connectors` `.d.ts` in parity with their runtime exports.
197
+ - The Doto webfont now ships as **woff2 only** (Brotli) instead of uncompressed
198
+ TTF: ~5.7 kB per weight vs ~137 kB, cutting the six-weight payload from ~823 kB
199
+ to ~35 kB (the dot-matrix glyphs compress ~96%) and shrinking the unpacked
200
+ tarball by roughly the same. No TTF fallback is carried — woff2 is supported by
201
+ the entire browser floor (ADR-0002: Chrome 125 / Safari 18 / Firefox 129).
202
+ `@font-face` is internal, so this is transparent to consumers; only self-hosts
203
+ that referenced `fonts/doto-*.ttf` directly need to point at `*.woff2`.
204
+ - `docs/architecture.md` now ships in the package, so the offline rationale the
205
+ shipped ADRs link to resolves inside the tarball.
206
+ - `docs/stability.md` clarifies that `data-surface`/`data-density`/
207
+ `data-contrast` are **convenience presets**, not part of the stability
208
+ contract; `data-theme` (light/dark) remains the contractual base.
209
+
210
+ ### Internal
211
+
212
+ - Token values are single-sourced in `tokens/index.js` (`cssVars`); the
213
+ `css/tokens.css` palette is generated from it, so the dark palette is authored
214
+ once instead of in three places (the shipped CSS is byte-identical).
215
+ - `behaviors/index.js` is split into per-behavior modules behind the same public
216
+ barrel (no surface change).
217
+ - Drift-gate consolidation (`assertFresh`), a Qwik type smoke + stronger
218
+ class-recipe wiring test, the APCA advisory widened to the accent text across
219
+ the core palette and every colorway (still advisory; WCAG 2.1 AA stays the
220
+ hard gate), an OLED computed-style smoke test, and several doc reconciliations.
221
+ - New `demos.spec` e2e sweep runs the console-error / uncaught-exception /
222
+ failed-response guards **and** an axe scan over every per-feature demo page
223
+ (annotations, legends, marks, connectors, spotlight, crosshair, selection,
224
+ report) in both themes and cross-browser — previously only `/demo/` was
225
+ guarded, so a throw or 404 on those SVG-heavy pages could not fail CI.
226
+ - The `check:dist` payload ceiling was raised to 80 kB raw / 14.5 kB gzip (from
227
+ 78 kB / 13.5 kB). The default bundle was sitting ~21 bytes under the old gzip
228
+ gate — the analytical primitives are opt-in leaves and stay out of it, so this
229
+ is residual prior growth; the bump restores a real ~3% raw / ~7% gzip margin
230
+ so an ordinary token addition no longer trips an unrelated PR.
231
+
7
232
  ## 0.4.1 — 2026-06-01
8
233
 
9
234
  Patch hardening for the public framework surface, plus the first step of the
@@ -79,6 +304,9 @@ modern-platform motion direction (see [ADR-0002](docs/adr/0002-scope-and-2026-ba
79
304
  - **[ADR-0003](docs/adr/0003-theme-model.md)** records the theme model: a binary
80
305
  light/dark base × one-knob derivation × orthogonal axes (colorway, surface,
81
306
  contrast, density), and why a flat named-theme catalog is rejected.
307
+ - React and Solid Vite examples, CI/release matrix coverage for those examples,
308
+ runtime binding tests, public API stability docs, a release runbook, and
309
+ `npm run size:report`.
82
310
 
83
311
  ### Changed
84
312
 
@@ -117,12 +345,6 @@ modern-platform motion direction (see [ADR-0002](docs/adr/0002-scope-and-2026-ba
117
345
  and the OKLCH accent ramp uses an explicit white/black neutral endpoint for
118
346
  cross-engine browser parity.
119
347
 
120
- ### Added
121
-
122
- - React and Solid Vite examples, CI/release matrix coverage for those examples,
123
- runtime binding tests, public API stability docs, a release runbook, and
124
- `npm run size:report`.
125
-
126
348
  ## 0.4.0 — 2026-05-31
127
349
 
128
350
  The color-system release — [ADR-0001](docs/adr/0001-color-system.md) steps 1–8.
@@ -0,0 +1,92 @@
1
+ {
2
+ "$comment": "Machine-readable rename/removal map for @ponchia/ui upgrades (classes, attributes, and tokens). Generated-by-hand from CHANGELOG BREAKING sections; consumed by docs/migrations/*.md and any codemod/sed recipe. 'safe' rules are mechanically rewritable (whole-token, no semantic change); 'manual' rules need human judgement (concept moved or removed, not a 1:1 rename).",
3
+ "migrations": [
4
+ {
5
+ "from": "0.2",
6
+ "to": "0.3",
7
+ "summary": "Entire non-ui-* legacy vocabulary removed; everything is now under the .ui-* contract and the check-classes drift gate.",
8
+ "safe": [
9
+ { "old": "skip-link", "new": "ui-skiplink" },
10
+ { "old": "site-nav", "new": "ui-sitenav" },
11
+ { "old": "site-menu", "new": "ui-sitemenu" },
12
+ { "old": "theme-toggle", "new": "ui-themetoggle", "prefix": true },
13
+ { "old": "app-shell", "new": "ui-app-shell", "prefix": true },
14
+ { "old": "app-rail", "new": "ui-app-rail", "prefix": true },
15
+ { "old": "app-topbar", "new": "ui-app-topbar", "prefix": true },
16
+ { "old": "app-toolbar", "new": "ui-app-toolbar", "prefix": true },
17
+ { "old": "app-nav", "new": "ui-app-nav", "prefix": true },
18
+ { "old": "app-panel", "new": "ui-app-panel", "prefix": true },
19
+ { "old": "app-content", "new": "ui-app-content", "prefix": true },
20
+ { "old": "app-main", "new": "ui-app-main", "prefix": true },
21
+ { "old": "app-metrics", "new": "ui-app-metrics", "prefix": true },
22
+ { "old": "app-metric", "new": "ui-app-metric", "prefix": true },
23
+ { "old": "app-empty-state", "new": "ui-app-empty-state", "prefix": true }
24
+ ],
25
+ "manual": [
26
+ {
27
+ "old": "hero / project-* / post-card / essay-* / page-* / home-* / signal-panel / worklog-summary",
28
+ "new": "the ui-* content layer",
29
+ "note": "Long-form content: .ui-prose / .ui-quote. Cards: .ui-card. Layout: .ui-grid / .ui-stack. Site chrome: the ui-site* shell. No 1:1 mapping — re-compose with the content primitives."
30
+ },
31
+ {
32
+ "old": "callout",
33
+ "new": "ui-alert",
34
+ "note": "Tone modifiers differ (.ui-alert--info/-success/-warning/-danger); re-pick the tone."
35
+ },
36
+ {
37
+ "old": "metric-tile",
38
+ "new": "ui-app-metric",
39
+ "note": "Now scoped to the admin shell vocabulary; standalone stat usage should wrap in .ui-app-metrics."
40
+ },
41
+ {
42
+ "old": "tag-list / tag",
43
+ "new": "ui-tags / ui-tag",
44
+ "note": "Compact variant .tag-list--compact → .ui-tags--compact; verify accent-on-accent contrast (see CHANGELOG 0.3.0 a11y fix)."
45
+ }
46
+ ],
47
+ "codemod": "See docs/migrations/0.2-to-0.3.md for a ready-to-run ripgrep+sed recipe covering the 'safe' rules."
48
+ },
49
+ {
50
+ "from": "0.3",
51
+ "to": "0.4",
52
+ "summary": "Additive colour-system release (ADR-0001); the default dist/bronto.css renders identically. No class or attribute renames. One orphan token pair removed.",
53
+ "safe": [],
54
+ "manual": [
55
+ {
56
+ "old": "--orange / --orange-soft",
57
+ "new": "(removed — re-declare in a consumer :root override if referenced)",
58
+ "note": "Orphan token pair: defined in the token mirrors but referenced by no shipped component and documented nowhere, and untiered under the new colour model. Removed under the CONTRIBUTING 'provably-unreferenced surface' exception. If you used it: :root { --orange: #a85f32; --orange-soft: rgb(168 95 50 / 0.13); }"
59
+ }
60
+ ],
61
+ "codemod": "No class codemod needed (no renames). See docs/migrations/0.3-to-0.4.md; audit usage with: rg -- '--orange' ."
62
+ },
63
+ {
64
+ "from": "0.4",
65
+ "to": "0.5",
66
+ "summary": "Adds the analytical-primitives suite (annotations, legend, marks, connectors, spotlight, crosshair, selection + the analytical.css roll-up); all additive/opt-in. Three breaking changes: the chart data key moved out of the report kit into the standalone Legends layer (`.ui-chart__legend`/`.ui-chart__swatch` removed); annotation arrowheads now render via the shared connectors geometry kernel (a small visual path change, no API change); and the marks/bracket-note rationed-accent tone was renamed `evidence`→`accent` to match the annotation/connector tone vocabulary (`.ui-annotation--evidence` stays — it's a marker variant, not a tone).",
67
+ "safe": [
68
+ { "old": "ui-chart__swatch", "new": "ui-legend__swatch" },
69
+ { "old": "ui-mark--evidence", "new": "ui-mark--accent" },
70
+ { "old": "ui-bracket-note--evidence", "new": "ui-bracket-note--accent" }
71
+ ],
72
+ "manual": [
73
+ {
74
+ "old": "ui.mark({ tone: 'evidence' }) / ui.bracketNote({ tone: 'evidence' })",
75
+ "new": "tone: 'accent'",
76
+ "note": "The rationed-accent tone option on the mark/bracket-note recipes is now 'accent' (was 'evidence'), matching ui.connector/ui.annotation. Do NOT rewrite ui.annotation({ variant: 'evidence' }) or the 'evidence' subject marker — those are a marker shape, not a tone, and are unchanged."
77
+ },
78
+ {
79
+ "old": "ui-chart__legend",
80
+ "new": "ui-legend",
81
+ "note": "Also import '@ponchia/ui/css/legend.css' beside report.css, and wrap each entry's content as <li class=\"ui-legend__item\"> … <span class=\"ui-legend__label\">…</span>. The swatch's --chart-color/--chart-pattern inline contract is unchanged; the categorical --chart-N colour is also available via .ui-legend__swatch--N. See docs/legends.md."
82
+ },
83
+ {
84
+ "old": "connectorEndArrow (annotations)",
85
+ "new": "connectorEndArrow (unchanged API)",
86
+ "note": "No code change needed. The function signature is identical; only the rendered arrowhead path differs slightly now that it shares the connectors geometry kernel. Re-baseline any exact-path SVG snapshot tests of annotation arrowheads."
87
+ }
88
+ ],
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
+ }
package/README.md CHANGED
@@ -3,12 +3,12 @@
3
3
  [![npm](https://img.shields.io/npm/v/@ponchia/ui?logo=npm)](https://www.npmjs.com/package/@ponchia/ui)
4
4
  [![npm provenance](https://img.shields.io/badge/npm-provenance-blue?logo=npm)](https://www.npmjs.com/package/@ponchia/ui#provenance)
5
5
  [![runtime deps](https://img.shields.io/badge/runtime%20deps-0-brightgreen)](https://github.com/Ponchia/bronto-ui/blob/main/package.json)
6
- [![dist](https://img.shields.io/badge/dist-~75kB%20%2F%20~13kB%20gzip-informational)](https://github.com/Ponchia/bronto-ui/blob/main/scripts/check-dist.mjs)
6
+ [![dist](https://img.shields.io/badge/dist-~76kB%20%2F%20~13kB%20gzip-informational)](https://github.com/Ponchia/bronto-ui/blob/main/scripts/check-dist.mjs)
7
7
  [![CI](https://github.com/Ponchia/bronto-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/Ponchia/bronto-ui/actions/workflows/ci.yml)
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, framework-agnostic UI framework built on token-driven restraint monochrome by default, one rationed accent, dot-matrix display type, hairline borders. Color is _tiered_: we don't decorate with it, we signal with it. The "Nothing"-inspired look is the default skin, not the architecture opt-in colorways (amber CRT · phosphor green · e-ink), a dot-matrix icon set, and a colourblind-safe data-viz palette prove the one knob is real. Zero runtime dependencies; re-brand the whole thing with one CSS variable.**
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.
12
12
 
13
13
  ### [Live demo →](https://ponchia.github.io/bronto-ui/) &nbsp;·&nbsp; [Theme playground →](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)
14
14
 
@@ -20,6 +20,8 @@ The demo is the kitchen sink — every component, light/dark, RTL, live theming.
20
20
 
21
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`.
22
22
 
23
+ 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
+
23
25
  ## Install
24
26
 
25
27
  ```bash
@@ -34,7 +36,7 @@ Or drop it in with no build step, straight from a CDN:
34
36
 
35
37
  ## Quick start
36
38
 
37
- **1. Load the CSS.** One flattened, minified bundle — the whole framework, one request (~75 kB raw / ~13 kB gzip):
39
+ **1. Load the CSS.** One flattened, minified bundle — the whole framework, one request (~76 kB raw / ~13 kB gzip):
38
40
 
39
41
  ```css
40
42
  @import '@ponchia/ui'; /* via a bundler */
@@ -100,6 +102,7 @@ Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lo
100
102
  - **Disclosure & nav** — tabs, accordion, segmented, breadcrumb, pagination, `ui-steps`, `ui-timeline`, `ui-pagehead`, `ui-kbd`.
101
103
  - **Shells** — an admin dashboard shell (`ui-app-*`) and a content/marketing site shell (`ui-site*`, `ui-container`).
102
104
  - **Prose** — `.ui-prose` styles raw, unclassed semantic HTML (Markdown / CMS / LLM output) with zero classes.
105
+ - **Analytical & communication primitives** _(opt-in)_ — `@ponchia/ui/css/analytical.css`: SVG **annotations** (subject/connector/note), standalone **legends**/data-keys, text/evidence **marks**, leader-line **connectors** (+ a pure `@ponchia/ui/connectors` geometry kernel), a guided-focus **spotlight**, a **crosshair**/readout, and a cross-cutting **selection** vocabulary. Each owns its visual grammar + pure geometry and refuses scales/state/hit-testing — figures that explain themselves, not a chart engine. Plus standalone **`source`/provenance** (trust) and **lifecycle `state`** leaves.
103
106
  - **Reports** _(opt-in)_ — `@ponchia/ui/css/report.css`, a static/PDF-first report grammar for LLM-authored HTML: covers, sections, findings, evidence, figures, chart wrappers and print utilities.
104
107
  - **Motion & dots** — the dot-matrix motif kit: dot grid, status dots, dot loaders, the orbital spinner, matrix reveal — all reduced-motion aware.
105
108
  - **Glyphs** — `@ponchia/ui/glyphs`, a 48-glyph dot-matrix icon set on the `.ui-dotmatrix` primitive (display marks + crisp `solid` inline icons + one-node `.ui-icon` mask rendering).
@@ -117,7 +120,7 @@ Everything accent-colored derives from a single `--accent` variable via `color-m
117
120
  .promo { --accent: #16a34a; } /* …or just this section green */
118
121
  ```
119
122
 
120
- Buttons, focus rings, dot motifs, accent borders and soft fills all follow automatically. Light/dark is `data-theme="light"` / `"dark"` on `<html>` (defaults to `prefers-color-scheme`); `data-density` and `data-contrast` give density and contrast presets. A full re-skin (radius, display face, dot density, surfaces) is a handful more token overrides — the "Nothing" look is the **default skin, not the architecture**.
123
+ Buttons, focus rings, dot motifs, accent borders and soft fills all follow automatically. Light/dark is `data-theme="light"` / `"dark"` on `<html>` (defaults to `prefers-color-scheme`); `data-density` and `data-contrast` give density and contrast presets. A full re-skin (radius, display face, dot density, surfaces) is a handful more token overrides — the default monochrome look is **one skin, not the architecture**.
121
124
 
122
125
  **One system, many skins.** That the knob is real isn't a claim — it ships: drop in `@ponchia/ui/css/skins.css` and set `data-bronto-skin="amber-crt | phosphor-green | e-ink"` on `<html>` for a complete, contrast-gated recolour (the derived accent family, focus ring, dot-matrix and glyphs all follow). Colour is governed in **tiers** — neutral canvas · one accent · locked status · display expression · opt-in data-viz — so it always earns its place; the full constitution is **[ADR-0001](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0001-color-system.md)**.
123
126
 
@@ -165,7 +168,7 @@ Recent-evergreen, by design. The framework targets the modern web platform — c
165
168
 
166
169
  ## Versioning
167
170
 
168
- 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.4.0` (and equivalently `^0.4.0`) resolves to `>=0.4.0 <0.5.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.
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.
169
172
 
170
173
  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.
171
174
 
@@ -181,4 +184,4 @@ Release candidates publish to the `next` dist-tag, never to `latest` — opt in
181
184
 
182
185
  [MIT](https://github.com/Ponchia/bronto-ui/blob/main/LICENSE) © Ponchia.
183
186
 
184
- The bundled **Doto** font (`fonts/*.ttf`) is © 2024 The Doto Project Authors and licensed separately under the [SIL Open Font License 1.1](https://github.com/Ponchia/bronto-ui/blob/main/fonts/OFL.txt) — see `fonts/OFL.txt`.
187
+ The bundled **Doto** font (`fonts/*.woff2`) is © 2024 The Doto Project Authors and licensed separately under the [SIL Open Font License 1.1](https://github.com/Ponchia/bronto-ui/blob/main/fonts/OFL.txt) — see `fonts/OFL.txt`.