@ponchia/ui 0.6.11 → 0.7.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 (61) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/MIGRATIONS.json +14 -0
  3. package/README.md +14 -6
  4. package/behaviors/dialog.d.ts.map +1 -1
  5. package/behaviors/dialog.js +14 -0
  6. package/behaviors/modal.d.ts +17 -13
  7. package/behaviors/modal.d.ts.map +1 -1
  8. package/behaviors/modal.js +281 -106
  9. package/behaviors/popover.d.ts.map +1 -1
  10. package/behaviors/popover.js +50 -2
  11. package/behaviors/splitter.d.ts +2 -0
  12. package/behaviors/splitter.d.ts.map +1 -1
  13. package/behaviors/splitter.js +15 -1
  14. package/behaviors/theme.d.ts +3 -2
  15. package/behaviors/theme.d.ts.map +1 -1
  16. package/behaviors/theme.js +10 -6
  17. package/bin/bronto-ui-check.mjs +286 -0
  18. package/classes/classes.json +7 -0
  19. package/classes/vscode.css-custom-data.json +1 -1
  20. package/css/disclosure.css +10 -0
  21. package/css/dots.css +43 -18
  22. package/css/feedback.css +35 -0
  23. package/css/report.css +0 -40
  24. package/css/site.css +10 -0
  25. package/css/tokens.css +1 -1
  26. package/dist/bronto.css +1 -1
  27. package/dist/css/disclosure.css +1 -1
  28. package/dist/css/dots.css +1 -1
  29. package/dist/css/feedback.css +1 -1
  30. package/dist/css/report-kit.css +1 -1
  31. package/dist/css/report.css +1 -1
  32. package/dist/css/site.css +1 -1
  33. package/dist/css/tokens.css +1 -1
  34. package/docs/adr/0004-prune-unused-adapters.md +34 -0
  35. package/docs/architecture.md +15 -11
  36. package/docs/command.md +18 -4
  37. package/docs/migrations/0.6-to-0.7.md +85 -0
  38. package/docs/package-contract.md +10 -5
  39. package/docs/reference.md +1 -1
  40. package/docs/reporting.md +8 -8
  41. package/docs/stability.md +36 -10
  42. package/docs/theming.md +49 -5
  43. package/docs/usage.md +68 -18
  44. package/docs/workbench.md +16 -2
  45. package/llms.txt +7 -3
  46. package/package.json +13 -3
  47. package/qwik/index.d.ts.map +1 -1
  48. package/qwik/index.js +4 -0
  49. package/react/index.d.ts.map +1 -1
  50. package/react/index.js +4 -0
  51. package/solid/index.d.ts.map +1 -1
  52. package/solid/index.js +4 -0
  53. package/svelte/index.d.ts.map +1 -1
  54. package/svelte/index.js +4 -0
  55. package/tokens/figma.variables.json +2 -2
  56. package/tokens/index.js +1 -1
  57. package/tokens/index.json +2 -2
  58. package/tokens/resolved.json +1 -1
  59. package/tokens/tokens.dtcg.json +2508 -399
  60. package/vue/index.d.ts.map +1 -1
  61. package/vue/index.js +4 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,119 @@
5
5
  |> `^0` / `*` wildcard does **not** protect you. See README → Versioning, and
6
6
  |> the deprecation policy in CONTRIBUTING.md.
7
7
 
8
+ ## 0.7.0 — 2026-07-20
9
+
10
+ A consumer-first contract-hardening release. Ten real applications and tools,
11
+ plus a web-platform and design-system landscape review, found more value in
12
+ repairing and pruning the existing surface than in adding components.
13
+
14
+ ### BREAKING
15
+
16
+ - **DTCG 2025.10 values.** `tokens.dtcg.json` now emits portable structured
17
+ color, dimension, duration, numeric, and cubic-bezier values. It no longer
18
+ emits CSS strings for typed values or `$value: null` placeholders. Derived
19
+ colors are resolved per light/dark theme; the original CSS expression remains
20
+ under `$extensions["com.ponchia.css"].authoredValue`. CSS-only shadow
21
+ expressions and em-based letter-spacing remain in `tokens.json` rather than
22
+ pretending to be portable DTCG values; the DTCG root extension lists those
23
+ deliberate omissions. Update JSON readers using
24
+ [`docs/migrations/0.6-to-0.7.md`](docs/migrations/0.6-to-0.7.md).
25
+
26
+ ### Added
27
+
28
+ - **Consumer contract checker.** The zero-dependency `bronto-ui-check` binary
29
+ scans consumer source for literal `ui-*` classes absent from `classes.json`
30
+ and unresolved Bronto-like `var(--*)` references. It understands local token
31
+ definitions, strips source comments, ignores Markdown prose and build/vendor
32
+ directories, supports explicit allowlists, and can emit JSON.
33
+ - **Non-drag splitter controls.** Buttons inside a splitter can use
34
+ `data-bronto-splitter-adjust="-10"` / `"10"` to change the first pane by a
35
+ signed percentage-point delta. This gives pointer users the same resize
36
+ function without requiring a dragging gesture.
37
+ - **DTCG semantic gate.** `check:dtcg` validates every emitted typed value and
38
+ rejects null placeholders or malformed structured values before publication.
39
+
40
+ ### Changed
41
+
42
+ - **Meter ownership.** The already-public `ui-meter__row`, `__label`, and
43
+ `__value` styling moves from optional `report.css` into core `feedback.css`.
44
+ Core consumers now receive the layout the public class contract promised;
45
+ report-kit output remains visually unchanged. Together with the explicit
46
+ 24×24px coarse-pointer utility-link floors below, this intentionally adds
47
+ 1,121 B raw / 164 B gzip to the default bundle versus 0.6.12 (now 89.9 kB raw /
48
+ 15.4 kB gzip) and raises the hard budget only enough to admit those contracts.
49
+ - **Release evidence.** CI and release documentation now treat real-consumer
50
+ literal validation, packed-tarball upgrades, and payload reporting as the
51
+ evidence for 1.0 readiness.
52
+
53
+ ### Fixed
54
+
55
+ - **Live dot composition.** `ui-dot--live` now describes motion only. A
56
+ standalone live dot defaults to success, while an explicit accent, success,
57
+ warning, danger, or info tone controls both the dot and its pulse ring,
58
+ including forced-colors mode.
59
+ - **OS theme synchronization.** An OS `prefers-color-scheme` change now emits
60
+ the existing `bronto:themechange` event when no explicit theme is set, keeping
61
+ consumer-rendered charts, icons, and labels synchronized with the CSS theme.
62
+ - **Named dialogs.** `initDialog()` now warns once when an opened native dialog
63
+ has no `aria-label`, `aria-labelledby`, or `title`. All shipped framework
64
+ examples provide a name.
65
+ - **Touch target floors.** Breadcrumb and footer utility links reach the WCAG
66
+ 2.5.8 24 CSS-pixel floor under a coarse pointer.
67
+
68
+ ### Deprecated
69
+
70
+ - **Framework adapter subpaths.** `@ponchia/ui/react`, `/solid`, `/qwik`,
71
+ `/svelte`, and `/vue` remain compatible in 0.7 but are scheduled for removal
72
+ no earlier than 0.8. None of the ten inspected consumers imports them; use the
73
+ vanilla behavior initializers in each framework's mount/cleanup lifecycle.
74
+ - **Controlled non-native modal.** `initModal()`, its adapter bindings, and
75
+ `data-bronto-modal` remain compatible in 0.7 but are scheduled for removal no
76
+ earlier than 0.8. Prefer native `<dialog>` with `initDialog()`.
77
+
78
+ ### Verified
79
+
80
+ - Unit, type, generated-artifact, package, schema, DTCG, class/token contract,
81
+ browser, accessibility, packed-example, and real-consumer checks are release
82
+ gates. The release evidence records consumer classes and imported surfaces
83
+ without exposing private project details.
84
+
85
+ ## 0.6.12 — 2026-07-10
86
+
87
+ A stabilization patch. It changes no public class, token name, behavior name,
88
+ or package path.
89
+
90
+ ### Changed
91
+
92
+ - **Small-text readability.** The `--text-2xs` value increases from `0.68rem`
93
+ to `0.72rem`. This raises the floor for form labels, table headings,
94
+ provenance metadata, report captions, and other dense secondary text without
95
+ changing the type scale's public names or the default CSS payload size.
96
+ - **1.0 stabilization mode.** Public catalog growth is frozen while real
97
+ consumers move onto one current minor. The stability guide now distinguishes
98
+ downstream-proven surfaces from package-only proof and unproven 1.0
99
+ candidates. New public surface needs explicit maintainer approval to reopen
100
+ the catalog.
101
+
102
+ ### Fixed
103
+
104
+ - **Controlled-modal ownership.** `initModal()` now reconciles one stack per
105
+ document instead of letting each modal own `inert` independently. Sibling
106
+ portal modals no longer inert the active top modal, nested stacks restore the
107
+ previous modal correctly, late-added background nodes join the trap, and a
108
+ popover opened from the top modal remains interactive when its panel is
109
+ portaled elsewhere. Cleanup still preserves author-owned `inert` state.
110
+ - **Maintainer documentation.** The architecture map now identifies
111
+ `css/generated.css` as authored trust-surface CSS, and the roadmap reflects
112
+ the current release and WOFF2 font payload.
113
+
114
+ ### Verified
115
+
116
+ - Focused unit coverage exercises sibling and nested modal stacks, portaled
117
+ popovers, late background nodes, focus restoration, and cleanup ownership.
118
+ The non-pixel browser suite carries the same sibling-stack, portal, and
119
+ late-node scenario.
120
+
8
121
  ## 0.6.11 — 2026-07-04
9
122
 
10
123
  A correctness, accessibility, and performance release drawn from a multi-pass
package/MIGRATIONS.json CHANGED
@@ -101,6 +101,20 @@
101
101
  }
102
102
  ],
103
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."
104
+ },
105
+ {
106
+ "from": "0.6",
107
+ "to": "0.7",
108
+ "summary": "Contract-hardening release. tokens.dtcg.json now uses conforming DTCG 2025.10 structured values instead of CSS strings/null placeholders. Splitters gain an additive non-drag pointer path. Framework adapters and initModal are deprecated, but remain compatible throughout 0.7.",
109
+ "safe": [],
110
+ "manual": [
111
+ {
112
+ "old": "tokens.dtcg.json scalar color/dimension values and $value:null CSS-expression placeholders",
113
+ "new": "DTCG 2025.10 structured typed values resolved per light/dark theme",
114
+ "note": "Update tooling to read color objects ({ colorSpace, components, alpha, optional hex }) and dimension objects ({ value, unit }). Read tokens.json when the authored CSS var()/color-mix() expression is required. CSS-only shadow expressions are not part of the portable DTCG projection."
115
+ }
116
+ ],
117
+ "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."
104
118
  }
105
119
  ]
106
120
  }
package/README.md CHANGED
@@ -3,7 +3,7 @@
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
- [![default CSS](https://img.shields.io/badge/default%20CSS-~89kB%20%2F%20~15kB%20gzip-informational)](https://github.com/Ponchia/bronto-ui/blob/main/scripts/check-dist.mjs)
6
+ [![default CSS](https://img.shields.io/badge/default%20CSS-~90kB%20%2F%20~15kB%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)
@@ -77,15 +77,16 @@ for the thesis.
77
77
  npm i @ponchia/ui
78
78
  ```
79
79
 
80
- Or drop it in with no build step, straight from a CDN:
80
+ Or drop it in with no build step, straight from a CDN (replace the version only
81
+ when deliberately upgrading across a breaking pre-1.0 minor):
81
82
 
82
83
  ```html
83
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.11/dist/bronto.css">
84
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.7.0/dist/bronto.css">
84
85
  ```
85
86
 
86
87
  ## Quick start
87
88
 
88
- **1. Load the CSS.** One flattened, minified default CSS bundle — the standard component set, one request (~89 kB raw / ~15 kB gzip) — that is `dist/bronto.css`, not the whole package tarball:
89
+ **1. Load the CSS.** One flattened, minified default CSS bundle — the standard component set, one request (~90 kB raw / ~15 kB gzip) — that is `dist/bronto.css`, not the whole package tarball:
89
90
 
90
91
  ```css
91
92
  @import '@ponchia/ui'; /* via a bundler */
@@ -187,7 +188,13 @@ Not an afterthought — a gate. Every contractual token pairing has a declared W
187
188
 
188
189
  ## Works with anything
189
190
 
190
- The CSS is the framework, so it works with React, Svelte/SvelteKit, Astro, Vue, Solid, Qwik or plain HTML — there's no component runtime to adopt. The optional `classes` and `behaviors` entrypoints pull in **no** UI framework and are SSR-safe. For React, Solid and Qwik there are also **optional thin bindings** — `@ponchia/ui/react`, `@ponchia/ui/solid` and `@ponchia/ui/qwik` wrap the behaviors as hooks (`useDialog`, `useToast`, …); `react`/`solid-js`/`@builder.io/qwik` are optional peer deps. Svelte and Vue get dependency-free lifecycle adapters too: `@ponchia/ui/svelte` exports actions, and `@ponchia/ui/vue` exports directives/plugin helpers over the same behavior layer.
191
+ The CSS is the framework, so it works with React, Svelte/SvelteKit, Astro, Vue,
192
+ Solid, Qwik or plain HTML — there's no component runtime to adopt. The optional
193
+ `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.
191
198
 
192
199
  Per-framework getting-started guides + runnable example apps live in the repo:
193
200
 
@@ -204,7 +211,8 @@ Per-framework getting-started guides + runnable example apps live in the repo:
204
211
 
205
212
  ## Extras
206
213
 
207
- - **Tokens as data** — `import tokens, { themeColor, cssVars } from '@ponchia/ui/tokens'` (plus `tokens.json`, W3C DTCG `tokens.dtcg.json`, `tokens/resolved.json` for concrete values in canvas/SVG/MapLibre, and `tokens/figma.variables.json` for local Figma Variables import/sync scripts).
214
+ - **Tokens as data** — `import tokens, { themeColor, cssVars } from '@ponchia/ui/tokens'` (plus authored `tokens.json`, a structured DTCG 2025.10 `tokens.dtcg.json`, `tokens/resolved.json` for concrete values in canvas/SVG/MapLibre, and `tokens/figma.variables.json` for local Figma Variables import/sync scripts).
215
+ - **Consumer contract checker** — after an upgrade, run `npx --no-install bronto-ui-check src` to catch unknown literal `ui-*` classes and unresolved Bronto token references in code, style, and template sources before build or deployment. Comments, generated/vendor directories, and Markdown prose are excluded.
208
216
  - **Chart colours for dashboards** — `import charts from '@ponchia/ui/charts.json' with { type: 'json' }` in Node ESM, or the same path through a bundler JSON import (resolved hex per theme; series 1 = your accent) plus the opt-in `@ponchia/ui/css/dataviz.css`.
209
217
  - **Static reports for LLMs** — add `@ponchia/ui/css/report-kit.css` for the complete report vocabulary, or `@ponchia/ui/css/report.css` plus the specific leaves a smaller report needs. Sidecar claim/source contracts can validate against `@ponchia/ui/schemas/report-claims.v1.schema.json`. Full cookbook: `docs/reporting.md`.
210
218
  - **Modern-platform motion** — overlays (modal/drawer/popover), toasts and the `<details>` accordion animate **in and out** with zero JS (`@starting-style` + `allow-discrete`, `::details-content` + `interpolate-size`). Progressive-enhancement extras: `.ui-scroll-progress` / `.ui-scroll-reveal` (scroll-driven, no JS) and `.ui-vt` for View Transitions. All degrade to a static end-state and respect `prefers-reduced-motion`. For smooth **cross-document** navigations, add the document-global one-liner to your own top-level (unlayered) CSS: `@view-transition { navigation: auto; }`.
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["dialog.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,sCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAgG3C"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["dialog.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,sCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA8G3C"}
@@ -26,8 +26,21 @@ export function initDialog({ root } = {}) {
26
26
  if (!doc) return noop;
27
27
  const managedDialogs = new Set();
28
28
  const focusRestorers = new Map();
29
+ const warnedNameless = new WeakSet();
29
30
  const canManageDialog = (dlg, origin) => host.contains(origin) || managedDialogs.has(dlg);
30
31
 
32
+ const warnIfNameless = (dlg) => {
33
+ const named =
34
+ dlg.hasAttribute('aria-label') ||
35
+ dlg.hasAttribute('aria-labelledby') ||
36
+ dlg.hasAttribute('title');
37
+ if (named || warnedNameless.has(dlg) || typeof console === 'undefined') return;
38
+ warnedNameless.add(dlg);
39
+ console.warn(
40
+ `[bronto] initDialog(): dialog #${dlg.id || '(without id)'} has no accessible name — add aria-label, aria-labelledby, or title so it is announced as a named dialog.`,
41
+ );
42
+ };
43
+
31
44
  const openFrom = (opener) => {
32
45
  const dlg = byIdInHost(host, opener.getAttribute('data-bronto-open'));
33
46
  if (!dlg || typeof dlg.showModal !== 'function' || dlg.open) return false;
@@ -47,6 +60,7 @@ export function initDialog({ root } = {}) {
47
60
  } catch {
48
61
  return false;
49
62
  }
63
+ warnIfNameless(dlg);
50
64
  managedDialogs.add(dlg);
51
65
  focusRestorers.set(dlg, restoreFocus);
52
66
  dlg.addEventListener('close', restoreFocus, { once: true });
@@ -12,21 +12,25 @@
12
12
  *
13
13
  * Mark the overlay `[data-bronto-modal]` (opt-in). On bind it gives the modal a
14
14
  * `role="dialog"` + `aria-modal="true"` (unless the author set a role) and
15
- * dev-warns when it has no accessible name, so it announces as a named modal
16
- * dialog parity with `initPopover`. The behavior watches its
17
- * `class` for `is-open`: on open it remembers the focused element, moves focus
18
- * into the modal (first focusable, else the panel itself), and **traps focus by
19
- * marking every sibling at each ancestor level `inert`** so the rest of the page
20
- * is non-focusable and non-interactive the modern, robust trap. On close it
21
- * un-inerts exactly what it inerted and returns focus to the opener. Bronto owns
22
- * focus only: the **consumer still owns open/close state** (the `is-open`
23
- * class). Escape dispatches a cancelable `bronto:modal:close`
15
+ * dev-warns when it has no accessible name. While open, a document-level stack
16
+ * reconciler keeps only the top controlled modal interactive, marks the rest of
17
+ * the page `inert`, admits an open popover owned by the top modal even when the
18
+ * panel is portaled elsewhere, and applies the trap to background nodes added
19
+ * after open. Nested and sibling portal modals therefore share one ownership
20
+ * model instead of independently inverting each other's `inert` state.
21
+ *
22
+ * Bronto owns focus only: the **consumer still owns open/close state** (the
23
+ * `is-open` class). Escape dispatches a cancelable `bronto:modal:close`
24
24
  * ({@link ModalCloseDetail}) on the modal so the consumer can drop `is-open` in
25
- * response; the behavior never changes visibility itself.
25
+ * response; the behavior never changes visibility itself. Closing a parent
26
+ * modal temporarily suspends any still-`is-open` controlled descendants; they
27
+ * resume at the top of the stack if the parent reopens.
28
+ *
29
+ * SSR-safe, idempotent per modal; returns a cleanup function.
26
30
  *
27
- * Best suited to a body-/portal-level overlay (the documented `.is-open` use
28
- * case); a deeply-nested modal still gets focus-into, focus-return, and the
29
- * Escape signal. SSR-safe, idempotent per modal; returns a cleanup function.
31
+ * @deprecated Use a native `<dialog>` with `initDialog()`. This controlled
32
+ * non-dialog path remains compatible in 0.7 and is scheduled for removal no
33
+ * earlier than 0.8 because no real consumer adopted it.
30
34
  *
31
35
  * @param {import('./internal.js').DelegateOpts} [opts]
32
36
  * @returns {import('./internal.js').Cleanup}
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["modal.js"],"names":[],"mappings":"AAsDA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA+G3C;;;;;YA7Ia,QAAQ"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["modal.js"],"names":[],"mappings":"AAmQA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA6E3C;;;;;YA/Ga,QAAQ"}