@ponchia/ui 0.9.0 → 0.10.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 (80) hide show
  1. package/CHANGELOG.md +70 -4
  2. package/MIGRATIONS.json +117 -27
  3. package/README.md +17 -9
  4. package/behaviors/index.d.ts +0 -2
  5. package/behaviors/index.d.ts.map +1 -1
  6. package/behaviors/index.js +0 -2
  7. package/behaviors/popover.js +4 -4
  8. package/classes/classes.json +24 -9
  9. package/classes/index.d.ts +8 -3
  10. package/classes/index.js +20 -3
  11. package/classes/vscode.css-custom-data.json +10 -10
  12. package/css/app.css +52 -30
  13. package/css/base.css +10 -14
  14. package/css/content.css +23 -21
  15. package/css/disclosure.css +17 -17
  16. package/css/feedback.css +15 -15
  17. package/css/forms.css +8 -7
  18. package/css/navigation.css +3 -3
  19. package/css/overlay.css +13 -29
  20. package/css/primitives.css +48 -28
  21. package/css/report.css +66 -42
  22. package/css/state.css +95 -6
  23. package/css/table.css +3 -3
  24. package/css/tokens.css +10 -10
  25. package/css/workbench.css +21 -9
  26. package/dist/bronto.css +1 -1
  27. package/dist/css/app.css +1 -1
  28. package/dist/css/base.css +1 -1
  29. package/dist/css/content.css +1 -1
  30. package/dist/css/disclosure.css +1 -1
  31. package/dist/css/feedback.css +1 -1
  32. package/dist/css/forms.css +1 -1
  33. package/dist/css/navigation.css +1 -1
  34. package/dist/css/overlay.css +1 -1
  35. package/dist/css/primitives.css +1 -1
  36. package/dist/css/report-kit.css +1 -1
  37. package/dist/css/report.css +1 -1
  38. package/dist/css/state.css +1 -1
  39. package/dist/css/table.css +1 -1
  40. package/dist/css/tokens.css +1 -1
  41. package/dist/css/workbench.css +1 -1
  42. package/docs/adr/0004-prune-unused-adapters.md +5 -1
  43. package/docs/adr/0005-productive-tools-and-editorial-reports.md +58 -0
  44. package/docs/adr/0006-trusted-publishing.md +92 -0
  45. package/docs/architecture.md +16 -23
  46. package/docs/command.md +1 -2
  47. package/docs/compositions.md +110 -0
  48. package/docs/frontier-primitives.md +1 -2
  49. package/docs/migrations/0.9-to-0.10.md +47 -0
  50. package/docs/package-contract.md +9 -12
  51. package/docs/reference.md +30 -18
  52. package/docs/reporting.md +15 -9
  53. package/docs/stability.md +19 -55
  54. package/docs/state.md +47 -0
  55. package/docs/usage.md +18 -30
  56. package/llms.txt +7 -18
  57. package/package.json +13 -55
  58. package/tokens/figma.variables.json +20 -20
  59. package/tokens/index.js +10 -10
  60. package/tokens/index.json +20 -20
  61. package/tokens/resolved.json +10 -10
  62. package/tokens/tokens.dtcg.json +20 -20
  63. package/behaviors/modal.d.ts +0 -45
  64. package/behaviors/modal.d.ts.map +0 -1
  65. package/behaviors/modal.js +0 -373
  66. package/qwik/index.d.ts +0 -48
  67. package/qwik/index.d.ts.map +0 -1
  68. package/qwik/index.js +0 -227
  69. package/react/index.d.ts +0 -45
  70. package/react/index.d.ts.map +0 -1
  71. package/react/index.js +0 -165
  72. package/solid/index.d.ts +0 -75
  73. package/solid/index.d.ts.map +0 -1
  74. package/solid/index.js +0 -172
  75. package/svelte/index.d.ts +0 -114
  76. package/svelte/index.d.ts.map +0 -1
  77. package/svelte/index.js +0 -197
  78. package/vue/index.d.ts +0 -116
  79. package/vue/index.d.ts.map +0 -1
  80. package/vue/index.js +0 -266
package/CHANGELOG.md CHANGED
@@ -5,6 +5,72 @@
5
5
  |> `^0` / `*` wildcard does **not** protect you. See README → Versioning, and
6
6
  |> the deprecation policy in CONTRIBUTING.md.
7
7
 
8
+ ## 0.10.0 — 2026-09-08
9
+
10
+ ### Changed
11
+
12
+ - **BREAKING: readable tool and report defaults.** The root respects the
13
+ browser's default text size. Everyday headings, labels, navigation, tables,
14
+ and controls use sans typography and sentence case. Explicit `ui-display`,
15
+ glyphs, and readouts retain the dot identity. Small text steps are 12/13/14px
16
+ at a 16px root; corner tokens use a restrained 2/4/6/8px scale.
17
+ - Service panels remove redundant framing, overview metrics stay compact, and
18
+ mobile navigation wraps. Inspectors adapt property rows to their own width.
19
+ Reports use 1.125rem prose, a 68ch measure, and 11pt print text.
20
+ - ADR-0005 and composition recipes replace the shipped-duplicate admission
21
+ rule with demonstrated task improvement. The default CSS budget is now
22
+ 100,000/18,000 bytes raw/gzip, restoring deliberate maintenance headroom.
23
+ - The example CI matrix derives from the shared registry. The complete browser
24
+ suite runs in three required shards, with unchanged cross-engine coverage.
25
+ Local Playwright uses an owned server on 8124 (`BRONTO_UI_TEST_PORT` override)
26
+ and refuses to reuse a live specimen server.
27
+
28
+ ### Removed
29
+
30
+ - **BREAKING:** the five framework adapter subpaths and optional framework
31
+ peers, deprecated in 0.7. Initialize vanilla behaviors in the host lifecycle.
32
+ - **BREAKING:** the controlled modal initializer, detail type, data attribute,
33
+ event, and `ui.modal({ open: true })` option. Use native dialog plus
34
+ `initDialog`; native modal and drawer styling remain.
35
+ - Unused adapter parity machinery and Solid/Qwik/Vue packed examples. React
36
+ and SvelteKit examples verify vanilla behavior mounting and cleanup.
37
+
38
+ ### Added
39
+
40
+ - `ui-timestrip` in the opt-in state leaf: the host supplies normalized event
41
+ positions and Bronto paints the rail, now marker, and severity marks. Old
42
+ events can remain visible at the window edge through `data-outside`.
43
+ - `ui-severity-tone` exposes the existing severity mapping without painting a
44
+ background, including for SVG consumers. `severity(level, { part: 'tone' })`
45
+ returns the corresponding class and level.
46
+ - `ui-chip--dense` and `ui.chip({ dense: true })` for static pane-header labels,
47
+ with pointer target floors when used on controls.
48
+ - A collapsed `details.ui-report__toc` recipe that keeps the decision first.
49
+
50
+ ### Fixed
51
+
52
+ - Single-column stacks and prose shrink inside narrow parents; the showcase's
53
+ nested legend grid fits its available width. Range inputs no longer add
54
+ browser margins outside their containing width.
55
+ - The workbench specimen stacks panes when narrow, provides native file-row
56
+ selection, and separates badge tone from row metadata styling.
57
+ - The service and report examples use favorable tones for decreasing latency.
58
+ Report annotations leave room for their stroke outside the drawing bounds.
59
+ - Development URI, YAML, and color parsers receive compatible security updates.
60
+
61
+ ### Internal
62
+
63
+ - Releases publish to npm by trusted publishing (OIDC) instead of a stored
64
+ access token. The token that authenticated previous releases expired
65
+ silently and surfaced only as a misleading `E404` after every gate and the
66
+ publish approval had passed; there is now no credential to expire. The
67
+ publisher identity is the repository, the workflow filename `release.yml`,
68
+ and the `npm-publish` environment — see
69
+ [ADR-0006](docs/adr/0006-trusted-publishing.md). The only packaged change is
70
+ that ADR joining the published documentation set.
71
+
72
+ See [the migration guide](docs/migrations/0.9-to-0.10.md).
73
+
8
74
  ## 0.9.0 — 2026-08-11
9
75
 
10
76
  Two additions and one correction, all from the same source: migrating a
@@ -53,7 +119,7 @@ downstream workbench onto 0.8.1 and watching where adoption stalled.
53
119
  - **`.ui-menu` no longer welds placement into the surface.** It used to declare
54
120
  `position: absolute` plus a trigger-relative offset, so a menu opened at a
55
121
  pointer — a canvas context menu, a long-press — could not use it at all, and
56
- consumers re-declared the panel, border, radius and shadow to get a surface.
122
+ consumers redeclared the panel, border, radius and shadow to get a surface.
57
123
  The dropdown placement is now `--dropdown` (unchanged behaviour, opted into)
58
124
  and `--at-pointer` takes a menu out of flow for a host that computes its own
59
125
  position.
@@ -149,7 +215,7 @@ consumer had to write because the framework did not provide it, or got wrong.
149
215
  neutral. From 0.8 the ten `SKIN_CANVAS_TOKENS` (`--bg`, `--bg-elevated`,
150
216
  `--panel`, `--panel-strong`, `--panel-soft`, `--line`, `--line-strong`,
151
217
  `--text`, `--text-soft`, `--text-dim`) are re-pointed per skin per theme.
152
- - **If you want the old look**, re-declare those ten tokens after the skin
218
+ - **If you want the old look**, redeclare those ten tokens after the skin
153
219
  import; they are ordinary custom properties on `:root[data-bronto-skin=…]`
154
220
  and un-layered app CSS wins.
155
221
  - **If you already hand-wrote a canvas** for a skin — the case this change
@@ -181,7 +247,7 @@ consumer had to write because the framework did not provide it, or got wrong.
181
247
  text in it and `--icon` decides whether the words are painted; they stay in
182
248
  the accessible name and in text-based test selectors either way. One markup
183
249
  shape serves both the labelled and icon-only forms, and no `aria-label` can
184
- drift out of sync with the visible wording. The slot also ellipsises rather
250
+ drift out of sync with the visible wording. The slot also ellipsis rather
185
251
  than wrapping, so a labelled button in a tight bar shrinks instead of pushing
186
252
  its neighbours out. `ui.button()` is unchanged; `cls.buttonLabel` is new.
187
253
  - **`.ui-button--dense`** — a size tier for bars whose *height* is the
@@ -1096,7 +1162,7 @@ and D2. The data-viz **palette** (`--chart-*`, `tokens/charts.json`) and the
1096
1162
  (build five real reports across the whole stack, review from every POV). The
1097
1163
  Vega CDN recipe now pins the `/build/*.min.js` UMD bundles and `renderer:'svg'`
1098
1164
  (a bare `cdn.jsdelivr.net/npm/vega@6` tag has no `window.vega`, so the previous
1099
- recipe rendered nothing); the file://-portable path (inline the config — an
1165
+ recipe rendered nothing); the `file://`-portable path (inline the config — an
1100
1166
  imported/fetched config is CORS-blocked from disk) is now explicit. New
1101
1167
  `docs/reporting.md` recipes: "Theming a live report" (the theme-toggle/re-embed
1102
1168
  foot-guns — clear the host, container-width-while-hidden, Mermaid source vs
package/MIGRATIONS.json CHANGED
@@ -6,27 +6,84 @@
6
6
  "to": "0.3",
7
7
  "summary": "Entire non-ui-* legacy vocabulary removed; everything is now under the .ui-* contract and the check-classes drift gate.",
8
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 }
9
+ {
10
+ "old": "skip-link",
11
+ "new": "ui-skiplink"
12
+ },
13
+ {
14
+ "old": "site-nav",
15
+ "new": "ui-sitenav"
16
+ },
17
+ {
18
+ "old": "site-menu",
19
+ "new": "ui-sitemenu"
20
+ },
21
+ {
22
+ "old": "theme-toggle",
23
+ "new": "ui-themetoggle",
24
+ "prefix": true
25
+ },
26
+ {
27
+ "old": "app-shell",
28
+ "new": "ui-app-shell",
29
+ "prefix": true
30
+ },
31
+ {
32
+ "old": "app-rail",
33
+ "new": "ui-app-rail",
34
+ "prefix": true
35
+ },
36
+ {
37
+ "old": "app-topbar",
38
+ "new": "ui-app-topbar",
39
+ "prefix": true
40
+ },
41
+ {
42
+ "old": "app-toolbar",
43
+ "new": "ui-app-toolbar",
44
+ "prefix": true
45
+ },
46
+ {
47
+ "old": "app-nav",
48
+ "new": "ui-app-nav",
49
+ "prefix": true
50
+ },
51
+ {
52
+ "old": "app-panel",
53
+ "new": "ui-app-panel",
54
+ "prefix": true
55
+ },
56
+ {
57
+ "old": "app-content",
58
+ "new": "ui-app-content",
59
+ "prefix": true
60
+ },
61
+ {
62
+ "old": "app-main",
63
+ "new": "ui-app-main",
64
+ "prefix": true
65
+ },
66
+ {
67
+ "old": "app-metrics",
68
+ "new": "ui-app-metrics",
69
+ "prefix": true
70
+ },
71
+ {
72
+ "old": "app-metric",
73
+ "new": "ui-app-metric",
74
+ "prefix": true
75
+ },
76
+ {
77
+ "old": "app-empty-state",
78
+ "new": "ui-app-empty-state",
79
+ "prefix": true
80
+ }
24
81
  ],
25
82
  "manual": [
26
83
  {
27
84
  "old": "hero / project-* / post-card / essay-* / page-* / home-* / signal-panel / worklog-summary",
28
85
  "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."
86
+ "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 \u2014 re-compose with the content primitives."
30
87
  },
31
88
  {
32
89
  "old": "callout",
@@ -41,7 +98,7 @@
41
98
  {
42
99
  "old": "tag-list / tag",
43
100
  "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)."
101
+ "note": "Compact variant .tag-list--compact \u2192 .ui-tags--compact; verify accent-on-accent contrast (see CHANGELOG 0.3.0 a11y fix)."
45
102
  }
46
103
  ],
47
104
  "codemod": "See docs/migrations/0.2-to-0.3.md for a ready-to-run ripgrep+sed recipe covering the 'safe' rules."
@@ -54,7 +111,7 @@
54
111
  "manual": [
55
112
  {
56
113
  "old": "--orange / --orange-soft",
57
- "new": "(removed re-declare in a consumer :root override if referenced)",
114
+ "new": "(removed \u2014 re-declare in a consumer :root override if referenced)",
58
115
  "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
116
  }
60
117
  ],
@@ -63,22 +120,31 @@
63
120
  {
64
121
  "from": "0.4",
65
122
  "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).",
123
+ "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`\u2192`accent` to match the annotation/connector tone vocabulary (`.ui-annotation--evidence` stays \u2014 it's a marker variant, not a tone).",
67
124
  "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" }
125
+ {
126
+ "old": "ui-chart__swatch",
127
+ "new": "ui-legend__swatch"
128
+ },
129
+ {
130
+ "old": "ui-mark--evidence",
131
+ "new": "ui-mark--accent"
132
+ },
133
+ {
134
+ "old": "ui-bracket-note--evidence",
135
+ "new": "ui-bracket-note--accent"
136
+ }
71
137
  ],
72
138
  "manual": [
73
139
  {
74
140
  "old": "ui.mark({ tone: 'evidence' }) / ui.bracketNote({ tone: 'evidence' })",
75
141
  "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."
142
+ "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 \u2014 those are a marker shape, not a tone, and are unchanged."
77
143
  },
78
144
  {
79
145
  "old": "ui-chart__legend",
80
146
  "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."
147
+ "note": "Also import '@ponchia/ui/css/legend.css' beside report.css, and wrap each entry's content as <li class=\"ui-legend__item\"> \u2026 <span class=\"ui-legend__label\">\u2026</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
148
  },
83
149
  {
84
150
  "old": "connectorEndArrow (annotations)",
@@ -91,16 +157,16 @@
91
157
  {
92
158
  "from": "0.5",
93
159
  "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.",
160
+ "summary": "Charting realignment. The local static bar-chart renderer (.ui-chart*) is removed \u2014 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
161
  "safe": [],
96
162
  "manual": [
97
163
  {
98
164
  "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
165
  "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."
166
+ "note": "No 1:1 class mapping \u2014 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
167
  }
102
168
  ],
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."
169
+ "codemod": "No codemod \u2014 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."
104
170
  },
105
171
  {
106
172
  "from": "0.6",
@@ -115,6 +181,30 @@
115
181
  }
116
182
  ],
117
183
  "codemod": "No source codemod. Update the DTCG reader at its JSON access boundary, then run npx --no-install bronto-ui-check against consumer source. See docs/migrations/0.6-to-0.7.md."
184
+ },
185
+ {
186
+ "from": "0.9",
187
+ "to": "0.10",
188
+ "summary": "Readable tool/report defaults; retire framework adapters and controlled modal.",
189
+ "safe": [],
190
+ "manual": [
191
+ {
192
+ "old": "@ponchia/ui/react / @ponchia/ui/solid / @ponchia/ui/qwik / @ponchia/ui/svelte / @ponchia/ui/vue",
193
+ "new": "@ponchia/ui/classes + @ponchia/ui/behaviors",
194
+ "note": "Initialize vanilla behaviors in the host mount lifecycle and return cleanup; wrappers and peers are removed."
195
+ },
196
+ {
197
+ "old": "initModal / data-bronto-modal / ui.modal({ open: true }) / bronto:modal:close",
198
+ "new": "native dialog + initDialog",
199
+ "note": "Use showModal/close and native cancel/close events; .is-open no longer opens a modal."
200
+ },
201
+ {
202
+ "old": "global dot headings and compact text defaults",
203
+ "new": "sans headings; explicit ui-display; productive tools and editorial reports",
204
+ "note": "Review real screens and preserve intentional display titles. Reports use a reading measure and separate print typography."
205
+ }
206
+ ],
207
+ "codemod": "See docs/migrations/0.9-to-0.10.md. Changes require consumer lifecycle and visual review; no blanket replacement is safe."
118
208
  }
119
209
  ]
120
210
  }
package/README.md CHANGED
@@ -19,11 +19,17 @@ app shells, navigation, forms, tables, feedback, overlays, prose, motion, and
19
19
  the token system that lets apps feel related without sharing a component runtime.
20
20
 
21
21
  The look is deliberately restrained: a mostly neutral canvas, one core accent
22
- for emphasis, dot-matrix display type, and hairline borders. Status colors,
22
+ for emphasis, selective dot-matrix display type, and restrained borders. Status colors,
23
23
  display-expression tokens, and data-viz colors are separate governed tiers, not
24
24
  extra brand accents. Opt-in skins re-point the root accent; Mermaid, D2, and
25
25
  Vega bridges use resolved renderer theme data instead of live CSS variables.
26
26
 
27
+ Everyday tools use readable sans typography and sentence-case labels. Reports
28
+ use a separate reading measure and print treatment. Use `ui-display` when a
29
+ large title should carry the dot-matrix signature; ordinary headings stay quiet.
30
+ [Composition recipes](docs/compositions.md) show a service overview, a narrow
31
+ inspector, and a decision report with their imports and acceptance checks.
32
+
27
33
  ## Start here
28
34
 
29
35
  - **Building an app or service shell?** Use the quick start below, then the
@@ -63,6 +69,12 @@ specificity fight. Print and reduced-motion rules still use `!important`
63
69
  deliberately where the framework must neutralize animation or layout at a media
64
70
  boundary.
65
71
 
72
+ One production consumer is **[Sense6](https://sense6.net/en/)**, a privacy-first
73
+ browser perception lab. Its static multilingual discovery pages and interactive
74
+ colour, reaction-time, hearing, and visual-detail experiments use Bronto's
75
+ shared shell, accessible controls, responsive layout, themes, and print rules
76
+ while keeping the experiment-specific visual identity in the application.
77
+
66
78
  It ships a complete, accessible **standard component set** because that is the
67
79
  identity layer every service consumes. Its sharper edge is the opt-in **tooling,
68
80
  analytical, and communication layer** sketched above. The line that holds it
@@ -81,7 +93,7 @@ Or drop it in with no build step, straight from a CDN (replace the version only
81
93
  when deliberately upgrading across a breaking pre-1.0 minor):
82
94
 
83
95
  ```html
84
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.9.0/dist/bronto.css">
96
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.10.0/dist/bronto.css">
85
97
  ```
86
98
 
87
99
  ## Quick start
@@ -191,10 +203,9 @@ Not an afterthought — a gate. Every contractual token pairing has a declared W
191
203
  The CSS is the framework, so it works with React, Svelte/SvelteKit, Astro, Vue,
192
204
  Solid, Qwik or plain HTML — there's no component runtime to adopt. The optional
193
205
  `classes` and framework-neutral `behaviors` entrypoints pull in **no** UI
194
- framework and are SSR-safe. The React, Solid, Qwik, Svelte, and Vue lifecycle
195
- adapter subpaths remain compatible in 0.7 but are deprecated for removal no
196
- earlier than 0.8; initialize vanilla behaviors in the framework's ordinary
197
- mount/cleanup lifecycle instead.
206
+ framework and are SSR-safe. Framework consumers initialize vanilla behaviors in their normal mount/cleanup
207
+ lifecycle. The unadopted framework adapters were removed in 0.10; see the
208
+ [migration guide](docs/migrations/0.9-to-0.10.md).
198
209
 
199
210
  Per-framework getting-started guides + runnable example apps live in the repo:
200
211
 
@@ -203,10 +214,7 @@ Per-framework getting-started guides + runnable example apps live in the repo:
203
214
  | Vanilla / Vite / plain HTML | [vanilla.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/vanilla.md) | [`examples/vanilla-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/vanilla-vite) |
204
215
  | Astro | [astro.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/astro.md) | [`examples/astro`](https://github.com/Ponchia/bronto-ui/tree/main/examples/astro) |
205
216
  | SvelteKit | [sveltekit.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/sveltekit.md) | [`examples/sveltekit`](https://github.com/Ponchia/bronto-ui/tree/main/examples/sveltekit) |
206
- | Vue | [vue.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/vue.md) | [`examples/vue-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/vue-vite) |
207
217
  | React | [react-solid.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/react-solid.md) | [`examples/react-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/react-vite) |
208
- | Solid | [react-solid.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/react-solid.md) | [`examples/solid-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/solid-vite) |
209
- | Qwik | [react-solid.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/react-solid.md) | [`examples/qwik-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/qwik-vite) |
210
218
  | Tailwind v4 bridge / cascade-layer interop | [tailwind.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/interop/tailwind.md) | [`examples/tailwind-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/tailwind-vite) |
211
219
 
212
220
  ## Extras
@@ -2,7 +2,6 @@ export { dismissible } from "./dismissible.js";
2
2
  export { initDisabledGuard } from "./inert.js";
3
3
  export { initTabs } from "./tabs.js";
4
4
  export { initDialog } from "./dialog.js";
5
- export { initModal } from "./modal.js";
6
5
  export { toast } from "./toast.js";
7
6
  export { initDisclosure } from "./disclosure.js";
8
7
  export { initMenu } from "./menu.js";
@@ -25,7 +24,6 @@ export type ThemeStorageOpts = import("./theme.js").ThemeStorageOpts;
25
24
  export type ApplyThemeOpts = import("./theme.js").ApplyThemeOpts;
26
25
  export type ThemeChangeDetail = import("./theme.js").ThemeChangeDetail;
27
26
  export type ToastOpts = import("./toast.js").ToastOpts;
28
- export type ModalCloseDetail = import("./modal.js").ModalCloseDetail;
29
27
  export type LegendToggleDetail = import("./legend.js").LegendToggleDetail;
30
28
  export type CrosshairMoveDetail = import("./crosshair.js").CrosshairMoveDetail;
31
29
  export type CommandSelectDetail = import("./command.js").CommandSelectDetail;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;sBAmBa,OAAO,eAAe,EAAE,OAAO;2BAC/B,OAAO,eAAe,EAAE,YAAY;+BACpC,OAAO,YAAY,EAAE,gBAAgB;6BACrC,OAAO,YAAY,EAAE,cAAc;gCACnC,OAAO,YAAY,EAAE,iBAAiB;wBACtC,OAAO,YAAY,EAAE,SAAS;+BAC9B,OAAO,YAAY,EAAE,gBAAgB;iCACrC,OAAO,aAAa,EAAE,kBAAkB;kCACxC,OAAO,gBAAgB,EAAE,mBAAmB;kCAC5C,OAAO,cAAc,EAAE,mBAAmB;gCAC1C,OAAO,cAAc,EAAE,iBAAiB;mCACxC,OAAO,eAAe,EAAE,oBAAoB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;sBAmBa,OAAO,eAAe,EAAE,OAAO;2BAC/B,OAAO,eAAe,EAAE,YAAY;+BACpC,OAAO,YAAY,EAAE,gBAAgB;6BACrC,OAAO,YAAY,EAAE,cAAc;gCACnC,OAAO,YAAY,EAAE,iBAAiB;wBACtC,OAAO,YAAY,EAAE,SAAS;iCAC9B,OAAO,aAAa,EAAE,kBAAkB;kCACxC,OAAO,gBAAgB,EAAE,mBAAmB;kCAC5C,OAAO,cAAc,EAAE,mBAAmB;gCAC1C,OAAO,cAAc,EAAE,iBAAiB;mCACxC,OAAO,eAAe,EAAE,oBAAoB"}
@@ -23,7 +23,6 @@
23
23
  * @typedef {import('./theme.js').ApplyThemeOpts} ApplyThemeOpts
24
24
  * @typedef {import('./theme.js').ThemeChangeDetail} ThemeChangeDetail
25
25
  * @typedef {import('./toast.js').ToastOpts} ToastOpts
26
- * @typedef {import('./modal.js').ModalCloseDetail} ModalCloseDetail
27
26
  * @typedef {import('./legend.js').LegendToggleDetail} LegendToggleDetail
28
27
  * @typedef {import('./crosshair.js').CrosshairMoveDetail} CrosshairMoveDetail
29
28
  * @typedef {import('./command.js').CommandSelectDetail} CommandSelectDetail
@@ -35,7 +34,6 @@ export { dismissible } from './dismissible.js';
35
34
  export { initDisabledGuard } from './inert.js';
36
35
  export { initTabs } from './tabs.js';
37
36
  export { initDialog } from './dialog.js';
38
- export { initModal } from './modal.js';
39
37
  export { toast } from './toast.js';
40
38
  export { initDisclosure } from './disclosure.js';
41
39
  export { initMenu } from './menu.js';
@@ -90,9 +90,9 @@ export function initPopover({ root } = {}) {
90
90
  return;
91
91
  }
92
92
 
93
- // A panel portaled out of a controlled modal starts in the trapped
94
- // background. Wait for initModal to admit that specific panel instead of
95
- // guessing how many microtasks its MutationObserver reconciliation needs.
93
+ // A host may temporarily keep a portaled panel inert. Wait until it
94
+ // admits this panel rather than guessing how many microtasks the host
95
+ // needs to reconcile its interaction state.
96
96
  const Observer = view?.MutationObserver;
97
97
  if (!Observer) {
98
98
  queueMicrotask(() => {
@@ -234,7 +234,7 @@ export function initPopover({ root } = {}) {
234
234
  // the browser's close-request then finds the dialog as the new topmost
235
235
  // element and dismisses it too. preventDefault() stops that native
236
236
  // close-request and stopPropagation() keeps it off other delegated keydown
237
- // listeners (e.g. initModal's), so only the popover closes — the documented
237
+ // listeners owned by the host, so only the popover closes — the documented
238
238
  // "popover + dialog open together" contract.
239
239
  e.preventDefault();
240
240
  e.stopPropagation();
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$comment": "@ponchia/ui class vocabulary as language-neutral data — validate emitted markup without executing the ESM cls map or parsing the .d.ts. Generated from classes/index.js — do not edit by hand; run `npm run classes:json:build`. Drift-checked in CI. `groups[].base` is null for a parts-only namespace (no standalone base class — do NOT emit it). A modifier whose name contains `__` (e.g. `ui-spark__bar--pos`) attaches to THAT part, not the base host. `states` is the author-applied `is-*` hooks (runtime/behavior-managed hooks are excluded); `behaviorAttributes` are the `data-bronto-*` wiring hooks the optional behaviors delegate on; `requiredAria` is the role/aria a generator must emit per component. `states` + `customProperties` are documented in docs/reference.md and ship outside `cls` by design.",
3
3
  "counts": {
4
- "classes": 677,
5
- "groups": 184
4
+ "classes": 683,
5
+ "groups": 186
6
6
  },
7
7
  "groups": {
8
8
  "ui-accordion": {
@@ -295,7 +295,8 @@
295
295
  "ui-chip": {
296
296
  "base": "ui-chip",
297
297
  "modifiers": [
298
- "ui-chip--accent"
298
+ "ui-chip--accent",
299
+ "ui-chip--dense"
299
300
  ],
300
301
  "parts": []
301
302
  },
@@ -1167,6 +1168,11 @@
1167
1168
  "ui-severity-row__title"
1168
1169
  ]
1169
1170
  },
1171
+ "ui-severity-tone": {
1172
+ "base": "ui-severity-tone",
1173
+ "modifiers": [],
1174
+ "parts": []
1175
+ },
1170
1176
  "ui-shortcut": {
1171
1177
  "base": "ui-shortcut",
1172
1178
  "modifiers": [],
@@ -1457,6 +1463,15 @@
1457
1463
  "ui-timeline__time"
1458
1464
  ]
1459
1465
  },
1466
+ "ui-timestrip": {
1467
+ "base": "ui-timestrip",
1468
+ "modifiers": [],
1469
+ "parts": [
1470
+ "ui-timestrip__axis",
1471
+ "ui-timestrip__event",
1472
+ "ui-timestrip__now"
1473
+ ]
1474
+ },
1460
1475
  "ui-toast": {
1461
1476
  "base": "ui-toast",
1462
1477
  "modifiers": [
@@ -1697,6 +1712,7 @@
1697
1712
  "ui-check",
1698
1713
  "ui-chip",
1699
1714
  "ui-chip--accent",
1715
+ "ui-chip--dense",
1700
1716
  "ui-citation",
1701
1717
  "ui-citation--chip",
1702
1718
  "ui-claim",
@@ -2086,6 +2102,7 @@
2086
2102
  "ui-severity-row",
2087
2103
  "ui-severity-row__meta",
2088
2104
  "ui-severity-row__title",
2105
+ "ui-severity-tone",
2089
2106
  "ui-shortcut",
2090
2107
  "ui-shortcut__sep",
2091
2108
  "ui-sidebar",
@@ -2194,6 +2211,10 @@
2194
2211
  "ui-timeline",
2195
2212
  "ui-timeline__item",
2196
2213
  "ui-timeline__time",
2214
+ "ui-timestrip",
2215
+ "ui-timestrip__axis",
2216
+ "ui-timestrip__event",
2217
+ "ui-timestrip__now",
2197
2218
  "ui-toast",
2198
2219
  "ui-toast--accent",
2199
2220
  "ui-toast--danger",
@@ -2824,12 +2845,6 @@
2824
2845
  "behavior": "initDialog",
2825
2846
  "note": "opt into backdrop light-dismiss (click the backdrop to close)"
2826
2847
  },
2827
- {
2828
- "name": "data-bronto-modal",
2829
- "on": "a controlled (non-<dialog>) .ui-modal overlay",
2830
- "behavior": "initModal",
2831
- "note": "inert focus-trap, focus-return, and Escape close signal for a consumer-owned .is-open modal; needs an accessible name"
2832
- },
2833
2848
  {
2834
2849
  "name": "data-bronto-menu",
2835
2850
  "on": "a native <details> dropdown",
@@ -51,6 +51,7 @@ export declare const cls: {
51
51
  readonly badgeDot: 'ui-badge--dot';
52
52
  readonly chip: 'ui-chip';
53
53
  readonly chipAccent: 'ui-chip--accent';
54
+ readonly chipDense: 'ui-chip--dense';
54
55
  readonly link: 'ui-link';
55
56
  readonly linkArrow: 'ui-link--arrow';
56
57
  readonly linkCta: 'ui-link--cta';
@@ -579,6 +580,11 @@ export declare const cls: {
579
580
  readonly severityRow: 'ui-severity-row';
580
581
  readonly severityRowTitle: 'ui-severity-row__title';
581
582
  readonly severityRowMeta: 'ui-severity-row__meta';
583
+ readonly severityTone: 'ui-severity-tone';
584
+ readonly timestrip: 'ui-timestrip';
585
+ readonly timestripAxis: 'ui-timestrip__axis';
586
+ readonly timestripNow: 'ui-timestrip__now';
587
+ readonly timestripEvent: 'ui-timestrip__event';
582
588
  readonly generated: 'ui-generated';
583
589
  readonly generatedLabel: 'ui-generated__label';
584
590
  readonly originLabel: 'ui-origin-label';
@@ -742,6 +748,7 @@ export interface ClaimOpts {
742
748
  }
743
749
  export interface ChipOpts {
744
750
  accent?: boolean;
751
+ dense?: boolean;
745
752
  }
746
753
  export interface LinkOpts {
747
754
  arrow?: boolean;
@@ -794,8 +801,6 @@ export interface DotbarOpts {
794
801
  }
795
802
  export interface ModalOpts {
796
803
  drawer?: boolean;
797
- /** Controlled non-dialog usage — adds only the is-open state; pair with initModal for focus management. */
798
- open?: boolean;
799
804
  }
800
805
  export interface TabOpts {
801
806
  active?: boolean;
@@ -1014,7 +1019,7 @@ export type SeverityLevel = (typeof SEVERITY_LEVELS)[number];
1014
1019
  * `'unknown'`, which paints the neutral tone. */
1015
1020
  export declare function severity(
1016
1021
  level: SeverityLevel | (string & {}) | null | undefined,
1017
- opts?: { part?: 'chip' | 'dot' | 'row' },
1022
+ opts?: { part?: 'chip' | 'dot' | 'row' | 'tone' },
1018
1023
  ): { class: string; 'data-level': string };
1019
1024
 
1020
1025
  /** Min/max for the value-bearing fills; defaults to 0–100. */
package/classes/index.js CHANGED
@@ -55,6 +55,7 @@ export const cls = Object.freeze({
55
55
  badgeDot: 'ui-badge--dot',
56
56
  chip: 'ui-chip',
57
57
  chipAccent: 'ui-chip--accent',
58
+ chipDense: 'ui-chip--dense',
58
59
  link: 'ui-link',
59
60
  linkArrow: 'ui-link--arrow',
60
61
  linkCta: 'ui-link--cta',
@@ -617,6 +618,14 @@ export const cls = Object.freeze({
617
618
  severityRow: 'ui-severity-row',
618
619
  severityRowTitle: 'ui-severity-row__title',
619
620
  severityRowMeta: 'ui-severity-row__meta',
621
+ // The tone as a value, for a mark Bronto does not ship (an SVG shape, a
622
+ // gradient stop): it paints nothing and only resolves `--severity-tone`.
623
+ severityTone: 'ui-severity-tone',
624
+ // timestrip — WHEN, beside the ladder's HOW BAD (css/state.css)
625
+ timestrip: 'ui-timestrip',
626
+ timestripAxis: 'ui-timestrip__axis',
627
+ timestripNow: 'ui-timestrip__now',
628
+ timestripEvent: 'ui-timestrip__event',
620
629
  // generated content / AI-trust surfaces (css/generated.css)
621
630
  generated: 'ui-generated',
622
631
  generatedLabel: 'ui-generated__label',
@@ -985,7 +994,7 @@ export const ui = {
985
994
  compare: ({ cols } = {}) => j(cls.compare, cols === 2 && cls.compare2up),
986
995
  reportFinding: ({ severity } = {}) => j(cls.reportFinding, reportFindingSeverity(severity)),
987
996
  claim: ({ status } = {}) => j(cls.claim, claimStatus(status)),
988
- chip: ({ accent } = {}) => j(cls.chip, accent && cls.chipAccent),
997
+ chip: ({ accent, dense } = {}) => j(cls.chip, accent && cls.chipAccent, dense && cls.chipDense),
989
998
  link: ({ arrow, cta } = {}) => j(cls.link, arrow && cls.linkArrow, cta && cls.linkCta),
990
999
  dot: ({ tone, live } = {}) => j(cls.dot, dotTone(tone), live && cls.dotLive),
991
1000
  dotgrid: ({ accent, dense } = {}) =>
@@ -1010,7 +1019,7 @@ export const ui = {
1010
1019
  dotspinner: ({ size } = {}) =>
1011
1020
  j(cls.dotspinner, size === 'sm' && cls.dotspinnerSm, size === 'lg' && cls.dotspinnerLg),
1012
1021
  dotbar: ({ indeterminate } = {}) => j(cls.dotbar, indeterminate && cls.dotbarIndeterminate),
1013
- modal: ({ drawer, open } = {}) => j(cls.modal, drawer && cls.modalDrawer, open && 'is-open'),
1022
+ modal: ({ drawer } = {}) => j(cls.modal, drawer && cls.modalDrawer),
1014
1023
  tab: ({ active } = {}) => j(cls.tab, active && 'is-active'),
1015
1024
  avatar: ({ size } = {}) =>
1016
1025
  j(cls.avatar, size === 'sm' && cls.avatarSm, size === 'lg' && cls.avatarLg),
@@ -1157,8 +1166,16 @@ export const SEVERITY_LEVELS = Object.freeze(['critical', 'error', 'warning', 'n
1157
1166
  /** `data-level` + the severity class, bundled so the attribute that carries the
1158
1167
  * meaning cannot be forgotten — the class alone paints the neutral tone and
1159
1168
  * silently loses the level. Unknown/absent levels resolve to `unknown`. */
1169
+ const SEVERITY_PARTS = {
1170
+ chip: 'severity',
1171
+ dot: 'severityDot',
1172
+ row: 'severityRow',
1173
+ // Paints nothing; resolves the tone for a mark Bronto does not ship.
1174
+ tone: 'severityTone',
1175
+ };
1176
+
1160
1177
  export const severity = (level, { part = 'chip' } = {}) => ({
1161
- class: part === 'dot' ? cls.severityDot : part === 'row' ? cls.severityRow : cls.severity,
1178
+ class: cls[SEVERITY_PARTS[part] ?? 'severity'],
1162
1179
  'data-level': SEVERITY_LEVELS.includes(level) ? level : 'unknown',
1163
1180
  });
1164
1181