@ponchia/ui 0.11.0 → 0.13.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 (76) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/MIGRATIONS.json +24 -0
  3. package/README.md +5 -5
  4. package/behaviors/forms.d.ts +1 -1
  5. package/behaviors/internal.d.ts +1 -1
  6. package/classes/classes.json +3 -1
  7. package/classes/index.d.ts +2 -0
  8. package/classes/index.js +3 -1
  9. package/classes/vscode.css-custom-data.json +64 -0
  10. package/css/base.css +2 -2
  11. package/css/blocknote.css +61 -0
  12. package/css/clamp.css +2 -2
  13. package/css/content.css +126 -0
  14. package/css/dataviz.css +117 -64
  15. package/css/disclosure.css +10 -10
  16. package/css/forms.css +8 -8
  17. package/css/legend.css +1 -2
  18. package/css/primitives.css +5 -6
  19. package/css/row.css +2 -2
  20. package/css/term.css +2 -2
  21. package/css/textref.css +2 -2
  22. package/css/toc.css +2 -2
  23. package/css/tokens.css +43 -0
  24. package/css/workbench.css +2 -2
  25. package/dist/bronto.css +1 -1
  26. package/dist/css/analytical.css +1 -1
  27. package/dist/css/base.css +1 -1
  28. package/dist/css/blocknote.css +1 -0
  29. package/dist/css/clamp.css +1 -1
  30. package/dist/css/content.css +1 -1
  31. package/dist/css/dataviz.css +1 -1
  32. package/dist/css/disclosure.css +1 -1
  33. package/dist/css/forms.css +1 -1
  34. package/dist/css/legend.css +1 -1
  35. package/dist/css/report-kit.css +1 -1
  36. package/dist/css/row.css +1 -1
  37. package/dist/css/term.css +1 -1
  38. package/dist/css/textref.css +1 -1
  39. package/dist/css/toc.css +1 -1
  40. package/dist/css/tokens.css +1 -1
  41. package/dist/css/workbench.css +1 -1
  42. package/docs/adr/0001-color-system.md +29 -0
  43. package/docs/architecture.md +1 -1
  44. package/docs/compositions.md +2 -2
  45. package/docs/contrast.md +24 -24
  46. package/docs/frontier-primitives.md +5 -0
  47. package/docs/interop/blocknote.md +60 -0
  48. package/docs/mermaid.md +1 -1
  49. package/docs/migrations/0.11-to-0.12.md +47 -0
  50. package/docs/package-contract.md +12 -2
  51. package/docs/reference.md +18 -1
  52. package/docs/renderer.md +100 -0
  53. package/docs/reporting.md +9 -9
  54. package/docs/stability.md +4 -2
  55. package/docs/theming.md +77 -20
  56. package/docs/usage.md +12 -8
  57. package/docs/vega.md +24 -23
  58. package/llms.txt +8 -4
  59. package/package.json +24 -12
  60. package/renderer/index.d.ts +203 -0
  61. package/renderer/index.d.ts.map +1 -0
  62. package/renderer/index.js +650 -0
  63. package/tokens/charts.d.ts +16 -10
  64. package/tokens/charts.js +65 -49
  65. package/tokens/charts.json +77 -29
  66. package/tokens/figma.variables.json +240 -0
  67. package/tokens/index.d.ts +2 -2
  68. package/tokens/index.js +30 -2
  69. package/tokens/index.json +32 -0
  70. package/tokens/mermaid.js +56 -56
  71. package/tokens/mermaid.json +56 -56
  72. package/tokens/resolved.json +17 -1
  73. package/tokens/tokens.dtcg.json +190 -0
  74. package/tokens/vega.d.ts +3 -3
  75. package/tokens/vega.js +111 -72
  76. package/tokens/vega.json +198 -126
package/CHANGELOG.md CHANGED
@@ -5,6 +5,104 @@
5
5
  |> `^0` / `*` wildcard does **not** protect you. See README → Versioning, and
6
6
  |> the deprecation policy in CONTRIBUTING.md.
7
7
 
8
+ ## 0.13.0 — 2026-10-01
9
+
10
+ ### Added
11
+
12
+ - **`ui-prose--blocks`: prose on a block editor's geometry.** A read view that
13
+ must put every line where a block editor (BlockNote's model) draws it: 3px
14
+ block padding instead of flow margins, line-height 1.5, headings with an 18px
15
+ lead and a 1.6/1.3/1.15em scale at weight 600, a 24px list column with disc,
16
+ circle and square, and the editor's task-row geometry. The px are exposed as
17
+ `--prose-block`, `--prose-heading-lead` and `--prose-list-column`.
18
+ `recipes.prose({ blocks: true })` emits it.
19
+ - **`css/blocknote.css`: BlockNote interop.** Maps BlockNote's `--bn-*` theme
20
+ variables (editor, menus, tooltips, side menu, selection, border, font,
21
+ radius) to bronto tokens, and its nine text highlights to the categorical
22
+ identity inks and tints, so the editor follows theme, skins, contrast and the
23
+ OLED surface. Import the unlayered build after BlockNote's stylesheet. See
24
+ [BlockNote interop](docs/interop/blocknote.md).
25
+ - **Half spacing steps for dense tool chrome.** `--space-0-5`, `--space-0-75`,
26
+ `--space-1-5` and `--space-2-5` (2, 3, 6 and 10px at a 16px root), scaled by
27
+ the density presets with the rest of the scale.
28
+ - **Workspace layers.** `--z-canvas`, `--z-chrome`, `--z-panel`, `--z-modal`,
29
+ `--z-menu`, `--z-tooltip` and `--z-navigation` name the stack of a tool drawn
30
+ over a canvas, aliased to the page layers where they mean the same.
31
+ - **Zoom-aware hairlines and focus rings.** A host that scales bronto UI marks
32
+ the scaled element `[data-ui-zoom]` and sets `--ui-zoom`; inside it `--ui-px`
33
+ is one screen pixel and `--hairline`, `--focus-ring-width` and
34
+ `--focus-ring-offset` are re-declared in it.
35
+
36
+ ### Changed
37
+
38
+ - Every bronto focus ring reads `--focus-ring-width` and `--focus-ring-offset`
39
+ instead of literal px. At the default zoom they are the same 2px, so nothing
40
+ moves; inside a `[data-ui-zoom]` surface a ring keeps its on-screen width.
41
+ - The default bundle grows from 92.8 kB / 16.0 kB gzip to 95.8 kB / 16.6 kB:
42
+ 1.9 kB is the block prose variant, the rest the new tokens and the focus-ring
43
+ variables. Notes are now the main reading surface, so block prose ships in
44
+ the core prose vocabulary rather than a leaf.
45
+
46
+ ### Internal
47
+
48
+ - `npm run check` runs every gate and ends with one line naming each gate
49
+ that failed; `npm run check -- --bail` stops at the first. It was an `&&`
50
+ chain that stopped at the first failure: since 0.8, 13 of the 20 failed CI
51
+ runs were the Dependabot dev-dependency group stopping at `check:exports`
52
+ on TypeScript 7, so no run measured the rest of the group. The gate list is
53
+ the `check:*` scripts themselves, so `check:chain`, which checked that the
54
+ hand-kept chain named every gate, is gone.
55
+ - The package contract no longer lists `react/`, `solid/`, `qwik/`,
56
+ `svelte/` and `vue/` as authored JS directories; the package has none. The
57
+ list is now read from `tsconfig.dts.json`.
58
+
59
+ ## 0.12.0 — 2026-10-01
60
+
61
+ ### Changed
62
+
63
+ - **BREAKING: a categorical palette with no accent slot.** `--chart-1..8` are
64
+ now eight fixed hues — blue, orange, aqua, yellow, magenta, green, violet,
65
+ red — authored as measured sRGB per theme. Series 1 is no longer
66
+ `var(--accent)`, so an ordinary first series stops reading as an alert, and
67
+ the `ACCENT` export of `@ponchia/ui/charts` is removed. The 0.11 set failed
68
+ the measurable palette checks on the package's own surfaces (Okabe-Ito
69
+ yellow and the slate outside the lightness band, the slate under the chroma
70
+ floor). The values come from a consumer that validated and shipped them as a
71
+ recorded divergence. `CATEGORICAL_HUES` names the slots.
72
+ - **BREAKING: `--chart-seq-*` is one blue hue in five steps.** `--chart-seq-6`
73
+ is removed. Step 1 sits nearest the surface in both themes.
74
+ - **BREAKING: the static Vega config is frameless.** `brontoVegaConfig()` sets
75
+ no plot frame, draws a single series in the first categorical hue, keeps a
76
+ `--panel` gap between adjacent fills and sets readable label sizes. It is now
77
+ generated from `@ponchia/ui/renderer`'s `vegaConfig()`, so the static and
78
+ runtime configs share one mapping. `brontoVegaAccent()` returns `--accent`
79
+ and `brontoVegaNeutral()` returns `--text-dim`.
80
+ - `check:charts` measures what a reader sees: per theme and against the panel,
81
+ the page and the OLED surfaces, each slot sits inside the OKLCH lightness
82
+ band and above the chroma floor, and adjacent slots stay apart under
83
+ simulated protanopia/deuteranopia (ΔE×100 ≥ 6) and normal vision (≥ 15).
84
+ All-pairs separation and sub-3:1 contrast are reported, not gated; the
85
+ pattern fill remains the second channel. ADR-0001 step 7 records the
86
+ amendment.
87
+
88
+ ### Added
89
+
90
+ - **Categorical identity tokens** in `css/dataviz.css`: `--cat-1..8` (the same
91
+ hues), `--cat-N-tint` (a 16% wash over `--panel`, so it follows skins and
92
+ OLED) and `--cat-N-ink` (text that holds 4.5:1 on the panel, the page and its
93
+ own tint, gated). For tags, participants and user-chosen tints — never
94
+ status. `charts.json` gains `hues`, `tint` and `ink`.
95
+ - **`@ponchia/ui/renderer`** — the live theme for renderers that cannot read
96
+ CSS. `readTokens()` resolves the bronto roles a renderer needs (surfaces,
97
+ inks, lines, accent, status, fonts, categorical set and ramps) to `#rrggbb`
98
+ or `rgba()` literals, following skins, contrast and the OLED surface.
99
+ `observeTokens()` calls back when one of them changed. `vegaConfig()` and
100
+ `xtermTheme()` map tokens to those renderers' configuration; `parseColor()`,
101
+ `formatColor()` and `resolveColor()` convert any CSS colour, including
102
+ `oklch()`, `lab()` and `color(display-p3 …)`.
103
+
104
+ See [the migration guide](docs/migrations/0.11-to-0.12.md).
105
+
8
106
  ## 0.11.0 — 2026-09-09
9
107
 
10
108
  ### Changed
package/MIGRATIONS.json CHANGED
@@ -224,6 +224,30 @@
224
224
  }
225
225
  ],
226
226
  "codemod": "No automatic rewrite: review complete consumer tasks and docs/migrations/0.10-to-0.11.md."
227
+ },
228
+ {
229
+ "from": "0.11",
230
+ "to": "0.12",
231
+ "summary": "Categorical palette with no accent slot, categorical identity tokens, runtime renderer tokens.",
232
+ "safe": [],
233
+ "manual": [
234
+ {
235
+ "old": "--chart-1 = var(--accent) / ACCENT from @ponchia/ui/charts",
236
+ "new": "fixed hues; paint an emphasised mark with var(--accent) or brontoVegaAccent(theme)",
237
+ "note": "ACCENT is removed. Charts that meant 'the brand' need an explicit accent encoding."
238
+ },
239
+ {
240
+ "old": "--chart-seq-6",
241
+ "new": "--chart-seq-1..5",
242
+ "note": "Re-map six-bin sequential figures to five bins."
243
+ },
244
+ {
245
+ "old": "brontoVegaConfig() framed plot, accent default mark",
246
+ "new": "frameless plot, first categorical hue as the default mark",
247
+ "note": "A spec's own config still wins; review dashboards that relied on the frame."
248
+ }
249
+ ],
250
+ "codemod": "No automatic rewrite: see docs/migrations/0.11-to-0.12.md."
227
251
  }
228
252
  ]
229
253
  }
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-~93kB%20%2F%20~16kB%20gzip-informational)](https://github.com/Ponchia/bronto-ui/blob/main/scripts/check-dist.mjs)
6
+ [![default CSS](https://img.shields.io/badge/default%20CSS-~96kB%20%2F%20~17kB%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)
@@ -93,12 +93,12 @@ Or drop it in with no build step, straight from a CDN (replace the version only
93
93
  when deliberately upgrading across a breaking pre-1.0 minor):
94
94
 
95
95
  ```html
96
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/bronto.css">
96
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.13.0/dist/bronto.css">
97
97
  ```
98
98
 
99
99
  ## Quick start
100
100
 
101
- **1. Load the CSS.** One flattened, minified default CSS bundle — the standard component set, one request (~93 kB raw / ~16 kB gzip) — that is `dist/bronto.css`, not the whole package tarball:
101
+ **1. Load the CSS.** One flattened, minified default CSS bundle — the standard component set, one request (~96 kB raw / ~17 kB gzip) — that is `dist/bronto.css`, not the whole package tarball:
102
102
 
103
103
  ```css
104
104
  @import '@ponchia/ui'; /* via a bundler */
@@ -171,7 +171,7 @@ Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lo
171
171
  - **Motion & dots** — the dot-matrix motif kit: dot grid, status dots, dot loaders, the orbital spinner, matrix reveal — all reduced-motion aware.
172
172
  - **Glyphs** — `@ponchia/ui/glyphs`, a 71-glyph dot-matrix icon set on the `.ui-dotmatrix` primitive (display marks + crisp `solid` inline icons + one-node `.ui-icon` mask rendering).
173
173
  - **Colorways** _(opt-in)_ — `data-bronto-skin="amber-crt | phosphor-green | e-ink"`: a root-level recolour of the one accent (OKLCH, per-theme, contrast-gated), never in the default bundle.
174
- - **Data-viz** _(opt-in)_ — a colourblind-safe chart palette (`--chart-*` + dot-matrix pattern fills, resolved hex in `charts.json`), gated under simulated protan/deutan/tritan vision. Charts only, never UI chrome.
174
+ - **Categorical + data-viz** _(opt-in)_ — eight fixed hues as chart series (`--chart-*`, sequential/diverging ramps, dot-matrix pattern fills) and as categorical identity (`--cat-*` with tint and text ink), measured per theme and surface. Never UI chrome. `@ponchia/ui/renderer` resolves them, with the chrome, for canvas/WebGL/SVG renderers.
175
175
 
176
176
  Full generated catalog of every class: **[docs/reference.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/reference.md)**. The decision guide (which primitive when): **[docs/usage.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/usage.md)**.
177
177
 
@@ -221,7 +221,7 @@ Per-framework getting-started guides + runnable example apps live in the repo:
221
221
 
222
222
  - **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).
223
223
  - **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.
224
- - **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`.
224
+ - **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, eight fixed hues) plus the opt-in `@ponchia/ui/css/dataviz.css`; for a live page that switches skin or theme, `@ponchia/ui/renderer` resolves the same palette and chrome at runtime.
225
225
  - **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`.
226
226
  - **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; }`.
227
227
  - **Editor IntelliSense** — point VS Code at the shipped custom-data file so every token autocompletes in `var(--…)`:
@@ -37,7 +37,7 @@ export type FormValidationOpts = {
37
37
  /**
38
38
  * Event-delegation root; default: `document`.
39
39
  */
40
- root?: Document | Element | null | undefined;
40
+ root?: Element | Document | null | undefined;
41
41
  /**
42
42
  * Localized validation-summary title. A summary/form
43
43
  * `data-bronto-error-summary-title` attribute overrides it, and an authored
@@ -21,6 +21,6 @@ export type DelegateOpts = {
21
21
  * Event-delegation root; also scopes which controls are queried. Default: `document`.
22
22
  * `null` means a scope was requested but is not ready yet, so the behavior no-ops.
23
23
  */
24
- root?: Document | Element | null | undefined;
24
+ root?: Element | Document | null | undefined;
25
25
  };
26
26
  //# sourceMappingURL=internal.d.ts.map
@@ -1,7 +1,7 @@
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": 695,
4
+ "classes": 696,
5
5
  "groups": 187
6
6
  },
7
7
  "groups": {
@@ -993,6 +993,7 @@
993
993
  "ui-prose": {
994
994
  "base": "ui-prose",
995
995
  "modifiers": [
996
+ "ui-prose--blocks",
996
997
  "ui-prose--compact"
997
998
  ],
998
999
  "parts": []
@@ -2040,6 +2041,7 @@
2040
2041
  "ui-property__label",
2041
2042
  "ui-property__value",
2042
2043
  "ui-prose",
2044
+ "ui-prose--blocks",
2043
2045
  "ui-prose--compact",
2044
2046
  "ui-provenance",
2045
2047
  "ui-provenance__item",
@@ -241,6 +241,7 @@ export declare const cls: {
241
241
  readonly eyebrowSm: 'ui-eyebrow--sm';
242
242
  readonly prose: 'ui-prose';
243
243
  readonly proseCompact: 'ui-prose--compact';
244
+ readonly proseBlocks: 'ui-prose--blocks';
244
245
  readonly quote: 'ui-quote';
245
246
  readonly quoteCite: 'ui-quote__cite';
246
247
  readonly container: 'ui-container';
@@ -822,6 +823,7 @@ export interface AvatarOpts {
822
823
  }
823
824
  export interface ProseOpts {
824
825
  compact?: boolean;
826
+ blocks?: boolean;
825
827
  }
826
828
  export interface ContainerOpts {
827
829
  narrow?: boolean;
package/classes/index.js CHANGED
@@ -255,6 +255,7 @@ export const cls = Object.freeze({
255
255
  eyebrowSm: 'ui-eyebrow--sm',
256
256
  prose: 'ui-prose',
257
257
  proseCompact: 'ui-prose--compact',
258
+ proseBlocks: 'ui-prose--blocks',
258
259
  quote: 'ui-quote',
259
260
  quoteCite: 'ui-quote__cite',
260
261
  // site shell
@@ -1036,7 +1037,8 @@ export const ui = {
1036
1037
  tab: ({ active } = {}) => j(cls.tab, active && 'is-active'),
1037
1038
  avatar: ({ size } = {}) =>
1038
1039
  j(cls.avatar, size === 'sm' && cls.avatarSm, size === 'lg' && cls.avatarLg),
1039
- prose: ({ compact } = {}) => j(cls.prose, compact && cls.proseCompact),
1040
+ prose: ({ compact, blocks } = {}) =>
1041
+ j(cls.prose, compact && cls.proseCompact, blocks && cls.proseBlocks),
1040
1042
  container: ({ narrow, wide } = {}) =>
1041
1043
  j(cls.container, narrow && cls.containerNarrow, wide && cls.containerWide),
1042
1044
  tag: ({ accent } = {}) => j(cls.tag, accent && cls.tagAccent),
@@ -201,6 +201,18 @@
201
201
  "name": "--focus-ring",
202
202
  "description": "Theme token. Light: `var(--accent)` · Dark: `var(--accent)`"
203
203
  },
204
+ {
205
+ "name": "--focus-ring-offset",
206
+ "description": "Global scale token. Value: `2px`"
207
+ },
208
+ {
209
+ "name": "--focus-ring-width",
210
+ "description": "Global scale token. Value: `2px`"
211
+ },
212
+ {
213
+ "name": "--hairline",
214
+ "description": "Global scale token. Value: `1px`"
215
+ },
204
216
  {
205
217
  "name": "--info",
206
218
  "description": "Theme token. Light: `#1f63c4` · Dark: `#6fb0e6`"
@@ -285,6 +297,22 @@
285
297
  "name": "--shadow-raised",
286
298
  "description": "Theme token. Light: `0 0 0 1px var(--line-strong)` · Dark: `0 0 0 1px var(--line-strong)`"
287
299
  },
300
+ {
301
+ "name": "--space-0-5",
302
+ "description": "Global scale token. Value: `0.125rem`"
303
+ },
304
+ {
305
+ "name": "--space-0-75",
306
+ "description": "Global scale token. Value: `0.1875rem`"
307
+ },
308
+ {
309
+ "name": "--space-1-5",
310
+ "description": "Global scale token. Value: `0.375rem`"
311
+ },
312
+ {
313
+ "name": "--space-2-5",
314
+ "description": "Global scale token. Value: `0.625rem`"
315
+ },
288
316
  {
289
317
  "name": "--space-2xl",
290
318
  "description": "Global scale token. Value: `2.5rem`"
@@ -409,6 +437,14 @@
409
437
  "name": "--tracking-wider",
410
438
  "description": "Global scale token. Value: `0.22em`"
411
439
  },
440
+ {
441
+ "name": "--ui-px",
442
+ "description": "Global scale token. Value: `1px`"
443
+ },
444
+ {
445
+ "name": "--ui-zoom",
446
+ "description": "Global scale token. Value: `1`"
447
+ },
412
448
  {
413
449
  "name": "--warning",
414
450
  "description": "Theme token. Light: `#806414` · Dark: `#d8bd72`"
@@ -421,10 +457,34 @@
421
457
  "name": "--z-base",
422
458
  "description": "Global scale token. Value: `0`"
423
459
  },
460
+ {
461
+ "name": "--z-canvas",
462
+ "description": "Global scale token. Value: `var(--z-base)`"
463
+ },
464
+ {
465
+ "name": "--z-chrome",
466
+ "description": "Global scale token. Value: `var(--z-sticky)`"
467
+ },
468
+ {
469
+ "name": "--z-menu",
470
+ "description": "Global scale token. Value: `var(--z-popover)`"
471
+ },
472
+ {
473
+ "name": "--z-modal",
474
+ "description": "Global scale token. Value: `var(--z-overlay)`"
475
+ },
476
+ {
477
+ "name": "--z-navigation",
478
+ "description": "Global scale token. Value: `80`"
479
+ },
424
480
  {
425
481
  "name": "--z-overlay",
426
482
  "description": "Global scale token. Value: `30`"
427
483
  },
484
+ {
485
+ "name": "--z-panel",
486
+ "description": "Global scale token. Value: `25`"
487
+ },
428
488
  {
429
489
  "name": "--z-popover",
430
490
  "description": "Global scale token. Value: `50`"
@@ -440,6 +500,10 @@
440
500
  {
441
501
  "name": "--z-toast",
442
502
  "description": "Global scale token. Value: `60`"
503
+ },
504
+ {
505
+ "name": "--z-tooltip",
506
+ "description": "Global scale token. Value: `70`"
443
507
  }
444
508
  ],
445
509
  "atDirectives": [
package/css/base.css CHANGED
@@ -164,8 +164,8 @@ input:focus-visible,
164
164
  select:focus-visible,
165
165
  textarea:focus-visible,
166
166
  [tabindex]:focus-visible {
167
- outline: 2px solid var(--focus-ring);
168
- outline-offset: 2px;
167
+ outline: var(--focus-ring-width) solid var(--focus-ring);
168
+ outline-offset: var(--focus-ring-offset);
169
169
  }
170
170
 
171
171
  /* Small global helpers reused across apps. */
@@ -0,0 +1,61 @@
1
+ /* ==========================================================================
2
+ blocknote — BlockNote's theme variables, mapped to bronto tokens.
3
+
4
+ INTEROP LEAF, opt-in. BlockNote (https://www.blocknotejs.org) themes its
5
+ editor, menus, side menu, toolbar and text highlights through `--bn-*`
6
+ custom properties on `.bn-root`, with its own light and dark values. Point
7
+ them at the bronto tokens and the editor follows the theme, skins, contrast
8
+ and the OLED surface like the rest of the page.
9
+
10
+ BlockNote's stylesheet is unlayered, and an unlayered rule outranks any
11
+ layered one, so import this leaf's UNLAYERED build, after BlockNote's:
12
+
13
+ @import '@blocknote/mantine/style.css';
14
+ @import '@ponchia/ui/css/unlayered/blocknote.css';
15
+
16
+ Text and background highlights are categorical identity (a colour a person
17
+ chose for a span), so they take `--cat-N-ink` and `--cat-N-tint` from
18
+ css/dataviz.css. Without that leaf they fall back to the status colours.
19
+ ========================================================================== */
20
+
21
+ .bn-root,
22
+ .bn-root[data-color-scheme] {
23
+ --bn-font-family: var(--sans);
24
+ --bn-border-radius: var(--radius-lg);
25
+ --bn-colors-editor-text: var(--text);
26
+ --bn-colors-editor-background: var(--panel);
27
+ --bn-colors-menu-text: var(--text);
28
+ --bn-colors-menu-background: var(--panel-strong);
29
+ --bn-colors-tooltip-text: var(--text);
30
+ --bn-colors-tooltip-background: var(--panel-soft);
31
+ --bn-colors-hovered-text: var(--text);
32
+ --bn-colors-hovered-background: var(--panel-soft);
33
+ --bn-colors-selected-text: var(--on-accent);
34
+ --bn-colors-selected-background: var(--accent);
35
+ --bn-colors-disabled-text: var(--text-dim);
36
+ --bn-colors-disabled-background: var(--panel-soft);
37
+ --bn-colors-shadow: var(--line);
38
+ --bn-colors-border: var(--line);
39
+ --bn-colors-side-menu: var(--text-dim);
40
+
41
+ /* Highlights: BlockNote's nine names onto the categorical hues. Gray is the
42
+ neutral ink; brown, which the palette has no hue for, is the orange ink. */
43
+ --bn-colors-highlights-gray-text: var(--text-dim);
44
+ --bn-colors-highlights-gray-background: var(--panel-soft);
45
+ --bn-colors-highlights-brown-text: var(--cat-2-ink, var(--warning));
46
+ --bn-colors-highlights-brown-background: var(--panel-soft);
47
+ --bn-colors-highlights-red-text: var(--cat-8-ink, var(--danger));
48
+ --bn-colors-highlights-red-background: var(--cat-8-tint, var(--panel-soft));
49
+ --bn-colors-highlights-orange-text: var(--cat-2-ink, var(--warning));
50
+ --bn-colors-highlights-orange-background: var(--cat-2-tint, var(--panel-soft));
51
+ --bn-colors-highlights-yellow-text: var(--cat-4-ink, var(--warning));
52
+ --bn-colors-highlights-yellow-background: var(--cat-4-tint, var(--panel-soft));
53
+ --bn-colors-highlights-green-text: var(--cat-6-ink, var(--success));
54
+ --bn-colors-highlights-green-background: var(--cat-6-tint, var(--panel-soft));
55
+ --bn-colors-highlights-blue-text: var(--cat-1-ink, var(--info));
56
+ --bn-colors-highlights-blue-background: var(--cat-1-tint, var(--panel-soft));
57
+ --bn-colors-highlights-purple-text: var(--cat-7-ink, var(--info));
58
+ --bn-colors-highlights-purple-background: var(--cat-7-tint, var(--panel-soft));
59
+ --bn-colors-highlights-pink-text: var(--cat-5-ink, var(--danger));
60
+ --bn-colors-highlights-pink-background: var(--cat-5-tint, var(--panel-soft));
61
+ }
package/css/clamp.css CHANGED
@@ -55,8 +55,8 @@
55
55
  }
56
56
 
57
57
  .ui-clamp__toggle:focus-visible + .ui-clamp__body + .ui-clamp__control {
58
- outline: 2px solid var(--focus-ring);
59
- outline-offset: 2px;
58
+ outline: var(--focus-ring-width) solid var(--focus-ring);
59
+ outline-offset: var(--focus-ring-offset);
60
60
  }
61
61
 
62
62
  .ui-clamp__less {
package/css/content.css CHANGED
@@ -308,6 +308,132 @@
308
308
  margin-block-start: var(--space-lg);
309
309
  }
310
310
 
311
+ /* --- Blocks variant — the block editor's geometry ---
312
+ For a surface that is both read and edited, where the editor is a block
313
+ editor (BlockNote's model): the read view has to put every line where the
314
+ editor will draw it, or the text jumps when the surface switches mode.
315
+ Blocks carry a small padding instead of flow margins; headings a lead above
316
+ and a 1.6/1.3/1.15em scale at weight 600; lists a fixed marker column with
317
+ disc, circle and square; a task row the editor's checkbox geometry. The
318
+ measure is released: a block surface is as wide as its container. The
319
+ geometry is the editor's own px, exposed so a host can retune it. */
320
+
321
+ .ui-prose--blocks {
322
+ --prose-measure: none;
323
+ --prose-block: 3px;
324
+ --prose-heading-lead: 18px;
325
+ --prose-list-column: 24px;
326
+
327
+ color: var(--text);
328
+ line-height: 1.5;
329
+ }
330
+
331
+ .ui-prose--blocks > *,
332
+ .ui-prose--blocks > * + *,
333
+ .ui-prose--blocks > * + :is(h1, h2, h3, h4, h5, h6),
334
+ .ui-prose--blocks li,
335
+ .ui-prose--blocks li + li,
336
+ .ui-prose--blocks li > *,
337
+ .ui-prose--blocks :is(ul, ol) :is(ul, ol),
338
+ .ui-prose--blocks blockquote > *,
339
+ .ui-prose--blocks blockquote > * + * {
340
+ margin-block: 0;
341
+ }
342
+
343
+ .ui-prose--blocks > :not(ul, ol),
344
+ .ui-prose--blocks li {
345
+ padding-block: var(--prose-block);
346
+ }
347
+
348
+ /* An item's own block ends before its nested list, as the editor nests it. */
349
+ .ui-prose--blocks li:has(> :is(ul, ol)) {
350
+ padding-block-end: 0;
351
+ }
352
+
353
+ .ui-prose--blocks li > :is(ul, ol) {
354
+ padding-block-start: var(--prose-block);
355
+ }
356
+
357
+ .ui-prose--blocks :is(h1, h2, h3, h4, h5, h6) {
358
+ padding-block: var(--prose-heading-lead) var(--prose-block);
359
+ border: 0;
360
+ font-size: 1em;
361
+ font-weight: 600;
362
+ line-height: 1.25;
363
+ }
364
+
365
+ .ui-prose--blocks h1 {
366
+ font-size: 1.6em;
367
+ }
368
+
369
+ .ui-prose--blocks h2 {
370
+ font-size: 1.3em;
371
+ }
372
+
373
+ .ui-prose--blocks h3 {
374
+ font-size: 1.15em;
375
+ }
376
+
377
+ .ui-prose--blocks :is(ul, ol) {
378
+ padding-inline-start: var(--prose-list-column);
379
+ }
380
+
381
+ .ui-prose--blocks ul {
382
+ list-style: disc;
383
+ }
384
+
385
+ .ui-prose--blocks ul ul {
386
+ list-style: circle;
387
+ }
388
+
389
+ .ui-prose--blocks ul ul ul {
390
+ list-style: square;
391
+ }
392
+
393
+ .ui-prose--blocks li::marker {
394
+ color: inherit;
395
+ }
396
+
397
+ /* A task row is the editor's: the checkbox centred in a hit area at the text
398
+ column, the text padded inside the block. A loose list may put the checkbox
399
+ in the item's paragraph rather than the item. */
400
+ .ui-prose--blocks li:has(> input[type='checkbox'], > p > input[type='checkbox']) {
401
+ margin-inline-start: calc(-1 * var(--prose-list-column));
402
+ padding-block: 10px;
403
+ list-style: none;
404
+ }
405
+
406
+ .ui-prose--blocks :is(li, li > p):has(> input[type='checkbox']) {
407
+ display: flex;
408
+ align-items: flex-start;
409
+ }
410
+
411
+ .ui-prose--blocks :is(li, li > p) > input[type='checkbox'] {
412
+ flex: none;
413
+ inline-size: 20px;
414
+ block-size: 20px;
415
+ margin: 2px 6px 0;
416
+ }
417
+
418
+ @media (pointer: coarse) {
419
+ .ui-prose--blocks li:has(> input[type='checkbox'], > p > input[type='checkbox']) {
420
+ padding-block: 16px;
421
+ }
422
+
423
+ .ui-prose--blocks :is(li, li > p) > input[type='checkbox'] {
424
+ margin-inline: 12px;
425
+ }
426
+ }
427
+
428
+ /* A quote is one block: its text on the body's line, its rule at the column. */
429
+ .ui-prose--blocks blockquote {
430
+ margin-inline: 0;
431
+ }
432
+
433
+ .ui-prose--blocks blockquote > * {
434
+ line-height: inherit;
435
+ }
436
+
311
437
  /* ==========================================================================
312
438
  ui-quote — pull-quote with attribution. A long-form companion to
313
439
  .ui-prose (works inside it or standalone). Emphasis via scale + a