@adia-ai/web-components 0.8.38 → 0.8.40
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.
- package/CHANGELOG.md +30 -0
- package/MIGRATION.md +243 -2
- package/components/agent-artifact/agent-artifact.css +1 -1
- package/components/agent-reasoning/agent-reasoning.css +2 -2
- package/components/agent-trace/agent-trace.css +3 -3
- package/components/alert/alert.css +1 -1
- package/components/avatar/avatar.css +1 -1
- package/components/badge/badge.css +1 -1
- package/components/button/button.css +6 -5
- package/components/calendar-picker/calendar-picker.css +5 -2
- package/components/card/card.css +3 -3
- package/components/chart/chart.a2ui.json +5 -5
- package/components/chart/chart.class.js +4 -4
- package/components/chart/chart.css +6 -6
- package/components/chart/chart.d.ts +2 -2
- package/components/chart/chart.yaml +3 -2
- package/components/chat-thread/chat-thread.css +1 -1
- package/components/code/code.css +6 -6
- package/components/combobox/combobox.css +8 -2
- package/components/command/command.a2ui.json +3 -0
- package/components/command/command.class.js +28 -6
- package/components/command/command.css +17 -6
- package/components/command/command.yaml +5 -0
- package/components/date-range-picker/date-range-picker.css +7 -1
- package/components/datetime-picker/datetime-picker.css +5 -1
- package/components/description-list/description-list.css +2 -2
- package/components/display-field/display-field.css +3 -3
- package/components/divider/divider.css +1 -1
- package/components/drawer/drawer.css +2 -2
- package/components/drilldown/drilldown.a2ui.json +3 -1
- package/components/drilldown/drilldown.class.js +12 -4
- package/components/drilldown/drilldown.css +9 -10
- package/components/drilldown/drilldown.yaml +2 -0
- package/components/empty-state/empty-state.css +2 -2
- package/components/field/field.css +1 -1
- package/components/heatmap/heatmap.css +2 -2
- package/components/inline-message/inline-message.css +1 -1
- package/components/input/input.css +5 -4
- package/components/integration-card/integration-card.css +4 -4
- package/components/kbd/kbd.css +1 -1
- package/components/list/list.css +2 -2
- package/components/modal/modal.class.js +68 -4
- package/components/nav/nav.a2ui.json +5 -0
- package/components/nav/nav.class.js +24 -4
- package/components/nav/nav.css +2 -2
- package/components/nav/nav.d.ts +2 -0
- package/components/nav/nav.yaml +18 -0
- package/components/nav-group/nav-group.css +3 -3
- package/components/nav-item/nav-item.css +2 -2
- package/components/option-card/option-card.css +1 -1
- package/components/otp-input/otp-input.css +1 -1
- package/components/page/page.css +2 -2
- package/components/pagination/pagination.css +1 -1
- package/components/pane/pane.css +1 -1
- package/components/progress-row/progress-row.css +2 -2
- package/components/qr-code/qr-code.a2ui.json +10 -10
- package/components/qr-code/qr-code.class.js +3 -3
- package/components/qr-code/qr-code.d.ts +10 -7
- package/components/qr-code/qr-code.yaml +13 -9
- package/components/range/range.css +1 -1
- package/components/rating/rating.css +1 -1
- package/components/richtext/richtext.css +3 -3
- package/components/segment/segment.css +5 -4
- package/components/select/select.class.js +30 -12
- package/components/select/select.css +14 -5
- package/components/spinner/spinner.css +1 -1
- package/components/stat/stat.css +3 -3
- package/components/step-progress/step-progress.css +1 -1
- package/components/stepper/stepper.css +2 -2
- package/components/swatch/swatch.css +8 -6
- package/components/table/table.a2ui.json +0 -10
- package/components/table/table.class.js +4 -4
- package/components/table/table.css +6 -9
- package/components/table/table.d.ts +0 -2
- package/components/table/table.yaml +0 -9
- package/components/table-toolbar/table-toolbar.css +1 -1
- package/components/tabs/tabs.css +1 -1
- package/components/tag/tag.css +2 -2
- package/components/tags-input/tags-input.css +1 -1
- package/components/textarea/textarea.css +1 -1
- package/components/time-picker/time-picker.css +1 -1
- package/components/timeline/timeline.css +4 -4
- package/components/toc/toc.css +1 -1
- package/components/toggle-group/toggle-group.class.js +13 -11
- package/components/toggle-group/toggle-group.css +14 -8
- package/components/toggle-group/toggle-group.d.ts +5 -0
- package/components/toggle-group/toggle-group.yaml +7 -0
- package/components/toggle-group/toggle-option.a2ui.json +5 -0
- package/components/toggle-group/toggle-option.yaml +14 -2
- package/components/tooltip/tooltip.css +1 -1
- package/components/tour/tour.css +2 -2
- package/components/tree/tree.css +1 -1
- package/custom-elements.json +101 -89
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +1 -1
- package/dist/theme-provider.min.js +3 -3
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +97 -94
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -1
- package/styles/type/scale.css +6 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
2
|
|
|
3
|
+
## [0.8.40] — 2026-08-15
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- **BREAKING (ships in 0.8.40, no deprecation alias): `toggle-group-ui` drops the legacy `data-selected` parallel stamp on `toggle-option-ui` children, per [ADR-0056](../../docs/adr/adr-0056-selection-item-selected-convention.md) (gh#1303).** The additive half of ADR-0056 (`0.8.39`) shipped `toggle-option-ui`'s declared, reflected `selected` prop alongside the pre-existing `data-selected` stamp, scoped that way pending operator sign-off on when the breaking removal would ride. That removal now lands: `toggle-group.class.js`'s render pass no longer sets/clears `data-selected`; `selected` (already the only prop `toggle-group.css` styled) is the sole current-state surface, matching `segment-ui`'s convention. The `DEPRECATED` markers in `toggle-option.yaml`/`toggle-group.yaml` are removed along with the attribute they described. `toggle-group.test.js`'s named deprecation case (`'DEPRECATED — still stamps data-selected in parallel'`) flips to assert the stamp is gone. See the migration guide's [§ Upcoming — `toggle-option-ui` drops the legacy `data-selected` stamp](../../.claude/docs/MIGRATION%20GUIDE.md#upcoming--toggle-option-ui-drops-the-legacy-data-selected-stamp-0840-adr-0056).
|
|
7
|
+
- **`table-ui[density]` converges onto the global attribute grammar (ADR-0054, gh#1300).** The component-local `compact | standard | comfortable` enum is removed (`table.yaml`, the reflected `density` prop + `getState()`/`setState()` persistence in `table.class.js`, the `:scope[density="…"]` CSS overrides in `table.css`) — `[density]` on `table-ui` is now the ordinary ambient global attribute (`compact | spacious`, unset = the middle), which `--table-py`/`--table-px` already read via `--a-space-*` (no CSS change needed beyond removing the now-redundant local override). **Breaking, no deprecation alias:** `density="compact"` is unchanged, `density="standard"` becomes the absent attribute, `density="comfortable"` becomes `density="spacious"`. Rides the ratified **0.8.40** breaking wave.
|
|
8
|
+
- **`chart-ui[radius]` renamed to `chart-ui[corner-radius]` (ADR-0054, gh#1300).** Same `Number` type, same `default: null` (falls back to `--a-radius`), same behavior — the collision was with the global preset-enum `[radius]` (`sharp`/`rounded`/`round`), which a numeric px value can't share a name with. **Breaking, no deprecation alias**, rides the ratified **0.8.40** breaking wave.
|
|
9
|
+
- **BREAKING (ships in 0.8.40): `qr-code-ui`'s reflected `[margin]` attribute is renamed `[quiet-zone]` (property `quietZone`), per [ADR-0053](../../docs/adr/adr-0053-no-shadowing-global-attributes.md) (gh#1299).** `qr-code-ui[margin]` silently collided with the framework's global `[margin]` Scale attribute — both accepted the identical `margin="4"` syntax but resolved to unrelated meanings (QR quiet zone in grid cells vs. global box-model spacing) with no error surfaced. Same type/default/reflection; only the name changes. No deprecation alias — `margin` on `qr-code-ui` now means the global Scale attribute. See the migration guide's [§ Upcoming — qr-code-ui quiet-zone rename](../../.claude/docs/MIGRATION%20GUIDE.md#upcoming--qr-code-ui-quiet-zone-rename-adr-0053).
|
|
10
|
+
- **BREAKING (ships in 0.8.40): the legacy `--a-leading-*` line-height token family is retired; `--a-font-leading-*` is the single canonical leading scale, per [ADR-0052](../../docs/adr/adr-0052-leading-scale-consolidation.md) (gh#1298).** Two leading families coexisted in `styles/type/scale.css` with the same step names resolving to different values (`--a-leading-snug` = `1.3` vs. `--a-font-leading-snug` = `1.2`) — no obviously-correct token choice, which is why 55 component files had reached for a bare numeric literal instead. `--a-font-leading-*` gains a `none: 1` step to close its only gap; the 4 in-repo `--a-leading-*` consumers (`button`, `chat-thread`, `inline-message`, `segment`) are migrated by value-nearest judgment (no name-preserving aliases: `snug`→`normal`, `normal`→`relaxed`). The same sweep tokenized every other hardcoded typography literal in `components/*/*.css`: bare numeric `line-height` (56 files; `1.3`/`1.4` → `--a-font-leading-normal`, escape-valve `--a-font-leading-relaxed` for multi-line body copy), `em`-literal `letter-spacing` (12 files; `0.05em` → `--a-font-tracking-wide`), numeric `font-weight` (7 files, on-scale). New `npm run check:typography-tokens` gate (mirrors the brand-chrome/foundation-layer audit gates) fails on any of the three literal classes reappearing. See the migration guide's [§ Upcoming — leading-scale consolidation](../../.claude/docs/MIGRATION%20GUIDE.md#upcoming--leading-scale-consolidation-adr-0052).
|
|
11
|
+
|
|
12
|
+
### Maintenance
|
|
13
|
+
- **`dist/` bundles rebuilt** in this cut's window (6 file(s)) — regenerated from the source changes described above, not independent edits.
|
|
14
|
+
|
|
15
|
+
## [0.8.39] — 2026-08-15
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- **`toggle-option-ui` converges onto `segment-ui`'s declared, parent-managed, reflected `[selected]` prop (ADR-0056, gh#1303).** Found by `framework-alignment-agent`'s corpus-wide component-state-naming sweep: the two same-role selection-item primitives named their "currently selected" state differently — `segment-ui` declared a reflected `selected: Boolean` prop (yaml → catalog → generative grammar), while `toggle-option-ui` had no declared state at all; the parent (`toggle-group-ui`) instead stamped a private `data-selected` attribute invisible to the yaml SoT, catalog, and A2UI grammar. `toggle-option-ui` gains `selected` (`Boolean`, default `false`, reflected) in `toggle-option.yaml` + `toggle-group.class.js`; `toggle-group-ui` now sets `selected` on its children (the `UIToggleOption` render pass stamps `aria-pressed` from it, mirroring `segment-ui`'s `aria-checked`-from-`selected` pattern); `toggle-group.css`'s `:scope[data-selected]` style rule becomes `toggle-option-ui[selected]` (moved outside `@scope`, same Safari-17.x attribute-restyle workaround `segment.css` already uses). Behavior, keyboard model, and the group's `value` as the single source of truth are unchanged. **SCOPING RULING (additive only, not the full ADR):** `toggle-group-ui` keeps stamping the legacy `data-selected` attribute on options in parallel, alongside the new `selected` prop — marked **DEPRECATED** in `toggle-option.yaml`/`toggle-group.yaml` — because it was an undocumented hook external CSS may already target; removing it is the breaking half of ADR-0056 and rides the ratified **0.9.0** breaking wave (alongside ADR-0052/0053/0054) rather than landing in this patch. `toggle-group.test.js` (new) covers the reflected `[selected]` + `aria-pressed` pairing, group-managed single-selection, multi-select, and the `data-selected` parallel-stamp deprecation case (named so it's obvious which test flips at 0.9.0 removal); `segmented.test.js` gains a regression check that `segment-ui`'s reference `[selected]`/`aria-checked` pairing is unchanged.
|
|
19
|
+
### Fixed
|
|
20
|
+
- **Trigger-caret sizing — the universal caret-size ruling (`--a-icon-size: var(--a-caret-size)`, encoded on `select-ui`'s trigger caret) is now applied consistently across the input/picker family (gh#1314).** `date-range-picker-ui`'s trigger caret never applied the rule at all, so it rode the ambient icon size and rendered visibly larger than `select-ui`'s caret in mixed control rows (e.g. the admin Finance Batches filter bar; consumer defect ADIA2-8729). Sweeping the rest of the trigger-caret family for the same class of miss found three more members: `datetime-picker-ui`'s trigger caret was missing the rule the same way; `combobox-ui`'s default caret-down suffix icon was sized off `--combobox-font-size` (the same value its leading/prefix icon correctly uses) instead of `--a-caret-size`; `calendar-picker-ui`'s `[slot="caret"]` was likewise sized off its own `--calendar-picker-font-size`. All four now resolve `--a-icon-size` to `--a-caret-size` on the caret glyph specifically (name-guarded on `combobox-ui`/date-picker family so a consumer-slotted non-caret glyph is unaffected), so every trigger caret in the family reads as one size. `time-picker-ui` was audited and excluded — it has no chevron/trigger caret (segmented inline input only). New/updated regression coverage in `date-range-picker.test.js`, `datetime-picker.test.js`, `combobox.test.js`, and a new `calendar-picker.test.js` asserts each caret rule's declared `--a-icon-size` computed value (CSS-source assertion — happy-dom doesn't evaluate `@scope` via `getComputedStyle`, same documented limitation as `badge.test.js`/`tag.test.js`).
|
|
21
|
+
- **ADR-0055 — `command-ui`, `select-ui`'s searchable trigger, and `drilldown-ui`'s filter row no longer stamp a native `<input>` with no recorded ADR-0025 exception (gh#1302).** A corpus sweep (gh#1302) found three uncatalogued native `<input>` stamps: `command-ui`'s palette search field, `select-ui`'s searchable-trigger branch (ADR-0025's own compliant-list entry predated/overlooked this branch), and `drilldown-ui`'s filter row (found while decomposing the issue, not in the original report). ADR-0055 rules no new exceptions get added — all three are replaced with patterns already in-tree: `command-ui` and `select-ui`'s searchable branch now use a `contenteditable="plaintext-only"` span carrying `role="combobox"` (the `combobox-ui` pattern — placeholder via the `[data-empty]::before` pseudo, same mechanism as `input-ui`/`combobox-ui`); `drilldown-ui`'s filter row now composes `<input-ui raw>` (the `search-ui` precedent). Behavior parity verified by a per-surface browser probe (typing, filtering, Escape-clears-query, Backspace-doesn't-navigate-back for drilldown) — not tests alone. `agent-trace`'s native `<details>`/`<summary>` disclosure toggle is ruled explicitly out of ADR-0025's scope by the same ADR (carries no submittable value). `command.yaml` gains the `input` slot entry the CSS rewrite now positions (`audit-slot-vocab-vs-css`). `drilldown.yaml`'s `composes:` list gains `input-ui` (+ `button-ui`, previously undeclared for the back affordance).
|
|
22
|
+
- **`scripts/dev/audit-stamped-native-buttons.mjs` extended to cover native `<input>` stamps, not just `<button>` (ADR-0055 follow-up, gh#1302).** Mirrors the existing button gate: no `createElement('input')` / `<input` in component source outside a `SANCTIONED_INPUT` map with a per-file reason. `input.class.js`'s `type="password"` branch is the one ADR-0025-named exception. Widening the scan surfaced pre-existing native `<input>` stamps outside gh#1302's audited scope — three `type="file"` OS-file-picker triggers (`chat-input.js`, `upload.class.js`, `admin-roster.js`) and two text-gathering surfaces (`otp-input.class.js`'s digit boxes, `table.class.js`'s filter-popover inputs) — all recorded as `PENDING` findings for a follow-up maintainer call, not fixed here (outside this issue's named scope).
|
|
23
|
+
- **`modal-ui` — `close` now fires reliably on every programmatic dismissal, including a parent-driven teardown race that was the actual root cause (gh#1295, adiav2 ADIA2-8581).** `close` previously depended entirely on the native `<dialog>` element's own queued `close` task re-dispatching it, which a consumer's own re-render could tear down before it ran. Real-browser reproduction (a vitest/happy-dom harness alone can't see this) traced the true root cause further: EVERY internal close path only ever runs from `<modal-ui>`'s own render effect, which reacts to the `open` property write via a microtask (signals.js) — `disconnectedCallback()` disposes that effect unconditionally. A consumer whose Confirm/Cancel handler flips `open = false` and, on the SAME tick, unmounts the modal (an ordinary framework re-render shape) tears the effect down before `#animateClose`'s exit-animation timer is ever even created, so `close` never fires and any caller awaiting it (`showConfirmDialog`-style APIs) hangs forever — confirmed reproducing, and NOT fixed, against PR #1296's authoritative-timer-dispatch approach, since that timer is one of the things the teardown race skips creating. `disconnected()` now emits `close` as a last-resort teardown fallback whenever the modal was open or mid-close at disconnect time, guarded by a once-only dispatch flag shared with the two other paths (the native `<dialog>` `close` listener, kept as a redundant net; `#animateClose`'s own timer, now also an authoritative direct dispatch — both absorbed from PR #1296, which correctly diagnosed the duration/unit bug below but couldn't reproduce this teardown race). `#getDuration()` also no longer silently drops a `s` vs `ms` unit on `--modal-duration` (`parseFloat('.25s')` read as `0.25`, a 0.25ms timer instead of 250ms — PR #1296's fix, kept as-is). `modal.test.js` gains per-dismissal-path close-emission coverage (button, Escape, backdrop, direct `.open=false`, raw `dialog.close()`, no-double-fire, re-open reset) plus the teardown-race repro itself.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **`nav-ui` — selecting a page now collapses every expanded group except the one containing the newly selected item (gh#1306).** Previously, `select()` only moved `[selected]` between items and never touched group `[open]` state, so any group a consumer or the collapsed-rail popover had expanded stayed expanded indefinitely, even after navigating elsewhere. Default-on: `select()` now closes every top-level `<nav-group-ui>` except the selected item's ancestor group (all groups, when the selection is ungrouped) — manual multi-expansion is still allowed right up until the next selection. New `[multi-expand]` attribute opts a consumer out, keeping every manually expanded group open across selections. Applies to every `select()` entrypoint: click, keyboard, programmatic, and the collapsed-rail popover option click (`nav-group.class.js`'s `showPopover()`, which itself calls `nav.select()`).
|
|
27
|
+
|
|
28
|
+
### Maintenance
|
|
29
|
+
- **`components/` touched in this release window** (39 file(s), e.g. `calendar-picker/calendar-picker.css`) — carried by the entries above.
|
|
30
|
+
- **`dist/` bundles rebuilt** in this cut's window (4 file(s)) — regenerated from the source changes described above, not independent edits.
|
|
31
|
+
|
|
3
32
|
## [0.8.38] — 2026-08-15
|
|
4
33
|
|
|
5
34
|
### Added
|
|
6
35
|
- **`drilldown-ui` — a new single-panel, multi-level drill-in menu primitive (gh#1285).** Replaces the hand-rolled miller-columns shape (two stacked list columns) that adiav2's Schema Manager had to build because the kit had no drill-down primitive — cleared the pre-build audit against `tree-ui` (inline expand/collapse, wrong for wide/deep >2-level data), `segmented-ui` (no overflow behavior for 18 namespaces), `tag-ui`-as-menu (no keyboard path), `list-ui`/`nav-ui`/`menu-ui`/`context-menu`/`breadcrumb-ui` (flat, not hierarchical drill-in) — none provide single-panel level-swap navigation with back/focus-restoration. Data-driven (`.items` tree of `{value, label, meta?, dot?, counts?, children?}` nodes; `children` may be sync or an async `(item) => array | Promise<array>` lazy loader, rendering a `<skeleton-ui>` loading level while pending). Full keyboard path (roving-tabindex listbox per level; ArrowRight/Enter drills in, ArrowLeft/Backspace goes back with focus restored to the item drilled from), `select` + `navigate` events, a `path` property that reflects to a JSON-encoded attribute both ways (hand-managed, not the generic `reflect:` mechanism — array values don't round-trip through `String(v)`) for deep-link/URL restore, `[filterable]` filter input, `[select-on-drill]` mode flag, a `breadcrumb` slot, row-native trailing count chips (not full `<badge-ui>`, which reads oversized at row density), and a horizontal slide transition that honors `prefers-reduced-motion: reduce` automatically (also suppressible via `[static]`).
|
|
7
36
|
|
|
8
37
|
### Fixed
|
|
38
|
+
- **`swatch-ui` — auto-contrast label/detail colors no longer fall back to raw hex, and detail-line dimming no longer uses `color-mix()`.** Found by a new `framework-alignment-agent` cohesion sweep: `--a-chrome-light`/`--a-chrome-dark` are always-defined foundational tokens (`styles/colors/semantics/features.css:124-125`), so the `var(--a-chrome-light, #fafafa)` / `var(--a-chrome-dark, #111)` fallbacks on the `[auto-contrast]` label rules were dead weight and a raw-CSS-color violation. The detail-line dimming also swapped `color-mix(in oklab, …, transparent)` for the plain token color plus `opacity` — not a browser-support fix (`color-mix()` is this repo's documented, Baseline-supported convention per `ADR-0007`/`BROWSER-COMPAT.md`), but a deliberate preference for a literal token over a computed color derivation.
|
|
9
39
|
- **`page-ui` header now ships the slot-gated grid its docs promised (gh#1253).** ADR-0009 recorded the named-slot vocabulary (`slot="icon"` / `slot="heading"` / `slot="action"`) as wired into four containers — Card, Drawer, Modal, and Page — but `page.css` never shipped its half; the slot attributes on a page header's children were dead metadata, so a block-level action child (e.g. `<toggle-scheme-ui>`) dropped to its own row instead of clustering. `page.css` gains the same `:has(> [slot])`-gated header grid as `card.css` (icon/heading/action columns, direct-child guard against nested false-positives), plus the `--page-header-gap` / `--page-heading-*` tokens `card-ui`'s pair already had. `page.yaml`'s `slots.default` and `page.examples.html` (new "Header slot-gated grid" demo) now describe the contract that's actually implemented.
|
|
10
40
|
- **`nav-ui` / `nav-item-ui` — `nav-select` now fires exactly once per click, and zero times re-clicking the already-selected item (gh#1254).** Root cause: two layered click handlers both drove selection for the same physical click — `nav-item-ui`'s own click handler called `nav.select(this)` *and* dispatched its own `nav-select`, while `nav-ui`'s click-delegation listener matched the same item on bubble and called `select()` again — three dispatches per click. `nav.select()` is now the single source of the event (idempotent: a no-op, including no hover-flush, when the item is already selected); `nav-item-ui` no longer dispatches its own copy, and `nav-ui`'s click listener no longer delegates item selection (it now only handles group expand/popover).
|
|
11
41
|
- **`view-transition` trait — no longer leaks unhandled `AbortError` rejections when a transition is superseded (gh#1255).** Only `transition.finished` had a `.catch()`; `ready` and `updateCallbackDone` are distinct promises that also reject (with `AbortError`) when a newer transition supersedes this one, and were previously uncaught. All three are now swallowed on abort — expected behavior for rapid navigation, not an error — with `fireEnd()` still driven solely by `finished`.
|
package/MIGRATION.md
CHANGED
|
@@ -54,6 +54,14 @@ Version cuts and migration scope:
|
|
|
54
54
|
|
|
55
55
|
- **`0.8.37`** — PATCH lockstep cut. **BREAKING: the a2ui / gen-ui estate split (ADR-0048).** Six published package names (`a2ui-runtime`, `a2ui-compose`, `a2ui-corpus`, `a2ui-retrieval`, `a2ui-validator`, `a2ui-mcp`) are replaced by four (`a2ui`, `gen-ui`, `gen-ui-mcp`, `a2ui-protocol-mcp`). **A patch-shaped version number does not make this non-breaking** — every old name is renamed. One-cycle re-export shims bridge the gap; the cut AFTER `0.8.37` retires them. See [§ 0.8.37 — the a2ui / gen-ui estate split](#0837--the-a2ui--gen-ui-estate-split-adr-0048).
|
|
56
56
|
|
|
57
|
+
- **Upcoming (`0.8.40` — attribute-grammar reconciliation, ADR-0054)** — **BREAKING, no deprecation alias:** `table-ui[density]` converges onto the ambient global `[density]` attribute — the component-local `compact`/`standard`/`comfortable` enum is removed. Migration: `density="compact"` stays `density="compact"`; `density="standard"` → drop the attribute (unset is the default); `density="comfortable"` → `density="spacious"`. `chart-ui[radius]` renames to `chart-ui[corner-radius]` (same `Number`/`null` semantics, same `--a-radius` fallback) — a mechanical attribute-name rename, no value-shape change. `swatch-ui[color]` and `noodles-ui[color]` are ratified exceptions and are unaffected. See [§ Upcoming — 0.8.40 attribute-grammar reconciliation](#upcoming-0840-attribute-grammar-reconciliation-adr-0054).
|
|
58
|
+
|
|
59
|
+
- **Upcoming (`qr-code-ui` quiet-zone rename, `0.8.40`)** — **BREAKING:** `<qr-code-ui>`'s reflected `[margin]` attribute is renamed `[quiet-zone]` (property `quietZone`) — same type, default (`4`), and reflection; only the name changes, per [ADR-0053](../../docs/adr/adr-0053-no-shadowing-global-attributes.md). `margin` on `qr-code-ui` now means the framework's **global** `[margin]` Scale attribute (box-model spacing), not the QR quiet zone — the two grammars silently collided on the same syntax with unrelated meanings. **No deprecation alias** — keeping `margin` as an alias would preserve the collision the rename exists to remove. Audit existing usages: `<qr-code-ui margin="4">` intending a quiet zone must become `<qr-code-ui quiet-zone="4">`. Ships in `0.8.40`. See [§ Upcoming — qr-code-ui quiet-zone rename](#upcoming--qr-code-ui-quiet-zone-rename-adr-0053).
|
|
60
|
+
|
|
61
|
+
- **Upcoming (leading-scale consolidation, `0.8.40`)** — **BREAKING, no aliases:** the legacy `--a-leading-*` token family is removed per [ADR-0052](../../docs/adr/adr-0052-leading-scale-consolidation.md) — `--a-font-leading-*` (+ new `--a-font-leading-none: 1` step) is now the single canonical leading scale. Value-nearest replacement table: `none→--a-font-leading-none` (1), `tight→--a-font-leading-snug` (1.2), `snug→--a-font-leading-normal` (1.35), `normal→--a-font-leading-relaxed` (1.5). The same gh#1298 sweep also tokenized every hardcoded `line-height`/`letter-spacing`/`font-weight` literal across `packages/web-components/components/*/*.css` (1.3 and 1.4 both → `--a-font-leading-normal`; 0.05em → `--a-font-tracking-wide`) and added a mechanized `npm run check:typography-tokens` gate. See [§ Upcoming — leading-scale consolidation](#upcoming--leading-scale-consolidation-adr-0052).
|
|
62
|
+
|
|
63
|
+
- **Upcoming (`toggle-option-ui` drops `data-selected`, `0.8.40`)** — **BREAKING, no deprecation alias:** `<toggle-group-ui>`'s legacy `data-selected` parallel stamp on its `<toggle-option-ui>` children is removed per [ADR-0056](../../docs/adr/adr-0056-selection-item-selected-convention.md) — the declared, reflected `selected` prop (shipped additively in `0.8.39`) is now the only current-state surface, matching `<segment-ui>`'s convention. Migration: any `[data-selected]` CSS or script targeting `toggle-option-ui` moves to `[selected]`. See [§ Upcoming — `toggle-option-ui` drops the legacy `data-selected` stamp](#upcoming--toggle-option-ui-drops-the-legacy-data-selected-stamp-0840-adr-0056).
|
|
64
|
+
|
|
57
65
|
Live demos and per-component docs at [ui-kit.exe.xyz/site/](https://ui-kit.exe.xyz/site/). The `adia-ui-migration` skill (in `.agents/skills/`) automates most of the mechanical sweeps in this guide.
|
|
58
66
|
|
|
59
67
|
---
|
|
@@ -79,8 +87,9 @@ The split is by concept, ruled in `docs/adr/adr-0048-a2ui-gen-ui-estate-split.md
|
|
|
79
87
|
`@adia-ai/a2ui-protocol-mcp`, before either ever published) ships one bin,
|
|
80
88
|
`adia-mcp`, dispatching two subcommands as separate processes:
|
|
81
89
|
`adia-mcp gen-ui` (30 tools — the generation surface, direct successor of
|
|
82
|
-
`@adia-ai/a2ui-mcp`) and `adia-mcp protocol` (4 tools — `validate_document`,
|
|
83
|
-
`get_registry_map`, `get_wiring_registry`, `protocol_status
|
|
90
|
+
`@adia-ai/a2ui-mcp`) and `adia-mcp protocol` (4 tools at the fold — `validate_document`,
|
|
91
|
+
`get_registry_map`, `get_wiring_registry`, `protocol_status`, joined since by
|
|
92
|
+
`get_catalog_ladder`; the first four renamed off
|
|
84
93
|
their original same-named-as-`gen-ui`-surface forms by gh#1248 before this
|
|
85
94
|
server ever published). The name `@adia-ai/a2ui-mcp` is **burned, never
|
|
86
95
|
reused**: it means "the generation MCP" to every consumer that has it
|
|
@@ -383,6 +392,238 @@ npm run check # in-repo consumers; downstream: your app's build + a visual pas
|
|
|
383
392
|
|
|
384
393
|
---
|
|
385
394
|
|
|
395
|
+
## Upcoming — `0.8.40` attribute-grammar reconciliation (ADR-0054)
|
|
396
|
+
|
|
397
|
+
**BREAKING, no deprecation alias.** [ADR-0054](../../docs/adr/adr-0054-attribute-grammar-reconciliation.md)
|
|
398
|
+
resolves two component-local attributes that shadowed the [global attribute
|
|
399
|
+
grammar](../../.claude/docs/specs/attribute-api-system.md) with divergent vocabularies —
|
|
400
|
+
`table-ui[density]` **converges** onto the global mechanism (it already did
|
|
401
|
+
the job), `chart-ui[radius]` **renames** (a numeric px value is a genuinely
|
|
402
|
+
different shape than the global preset enum). Per [ADR-0053](../../docs/adr/adr-0053-no-shadowing-global-attributes.md),
|
|
403
|
+
neither collision is exempted — `swatch-ui[color]` / `noodles-ui[color]` are
|
|
404
|
+
the only two ratified exceptions (documented in
|
|
405
|
+
[§11 of attribute-api-system.md](../../.claude/docs/specs/attribute-api-system.md#11-global-attribute-exemption-list)),
|
|
406
|
+
and neither is touched by this cut.
|
|
407
|
+
|
|
408
|
+
### `table-ui[density]` converges onto the global grammar
|
|
409
|
+
|
|
410
|
+
The component-local `compact | standard | comfortable` enum is removed —
|
|
411
|
+
`table-ui` no longer reflects a `density` prop or JS property at all.
|
|
412
|
+
`[density]` on `table-ui` is now the ordinary ambient global attribute
|
|
413
|
+
(`compact | spacious`, unset = the middle) — `--table-py`/`--table-px`
|
|
414
|
+
already derive from `--a-space-*` steps, which the global `[density]`
|
|
415
|
+
attribute already scales via `--a-density`.
|
|
416
|
+
|
|
417
|
+
**Value migration** (apply wherever `<table-ui density="…">` appears):
|
|
418
|
+
|
|
419
|
+
| Old value | New value |
|
|
420
|
+
|---|---|
|
|
421
|
+
| `density="compact"` | `density="compact"` (unchanged) |
|
|
422
|
+
| `density="standard"` | drop the attribute entirely (unset is the default) |
|
|
423
|
+
| `density="comfortable"` | `density="spacious"` |
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
# find every table-ui density usage in your tree
|
|
427
|
+
git grep -nE '<table-ui[^>]*\bdensity='
|
|
428
|
+
|
|
429
|
+
# comfortable → spacious (mechanical)
|
|
430
|
+
git grep -lz '<table-ui[^>]*density="comfortable"' | while IFS= read -r -d '' f; do
|
|
431
|
+
perl -i -pe 's/(<table-ui[^>]*density=")comfortable(")/${1}spacious${2}/g' "$f"
|
|
432
|
+
done
|
|
433
|
+
|
|
434
|
+
# standard → drop the attribute (review each hit; not always a safe blind sed
|
|
435
|
+
# across multi-line tags)
|
|
436
|
+
git grep -nE '<table-ui[^>]*density="standard"'
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
If you read/write a table's `density` as a JS property (`el.density`) or
|
|
440
|
+
persisted it via `table-ui`'s `getState()`/`setState()`, switch to
|
|
441
|
+
`getAttribute('density')`/`setAttribute('density', …)` — the reflected
|
|
442
|
+
property and the `getState()`/`setState()` `density` key are both gone.
|
|
443
|
+
Composites that forward density to an embedded `table-ui` (own component,
|
|
444
|
+
own vocabulary) must translate through the same table above before setting
|
|
445
|
+
the child's attribute — see `invoice-history.class.js`'s `mapDensity()` for
|
|
446
|
+
the pattern.
|
|
447
|
+
|
|
448
|
+
### `chart-ui[radius]` renames to `chart-ui[corner-radius]`
|
|
449
|
+
|
|
450
|
+
Same `Number` type, same `default: null` (falls back to `--a-radius`), same
|
|
451
|
+
behavior — only the attribute name changes.
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
git grep -nE '<chart-ui[^>]*\bradius='
|
|
455
|
+
git grep -lz '<chart-ui[^>]*radius="' | while IFS= read -r -d '' f; do
|
|
456
|
+
perl -i -pe 's/(<chart-ui[^>]*)\bradius=/${1}corner-radius=/g' "$f"
|
|
457
|
+
done
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
If you set it via JS, `chart.radius = 8` → `chart.cornerRadius = 8`.
|
|
461
|
+
|
|
462
|
+
### Verify
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
git grep -nE '<table-ui[^>]*\bdensity="(standard|comfortable)"' # must be 0
|
|
466
|
+
git grep -nE '<chart-ui[^>]*\bradius=' # must be 0
|
|
467
|
+
npm run check
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Upcoming — qr-code-ui quiet-zone rename (ADR-0053)
|
|
473
|
+
|
|
474
|
+
**BREAKING, ships in `0.8.40`.** `<qr-code-ui>`'s reflected `[margin]` attribute is
|
|
475
|
+
renamed `[quiet-zone]` (property `quietZone`) — same `number` type, same default (`4`), same
|
|
476
|
+
reflection; only the name changes.
|
|
477
|
+
|
|
478
|
+
**Why:** the framework's global attribute grammar (`styles/api/*.css`) is a pitch — one
|
|
479
|
+
grammar, inferable: `margin="4"` means the same thing on every element, resolving through one
|
|
480
|
+
Scale mechanism (`--a-margin`). `qr-code-ui` declared its own reflected `margin` meaning the QR
|
|
481
|
+
"quiet zone" in grid cells. Both grammars accepted the identical syntax with no error surfaced,
|
|
482
|
+
so an author reaching for `<qr-code-ui margin="4">` expecting global spacing silently got a
|
|
483
|
+
quiet-zone resize instead, and vice versa. [ADR-0053](../../docs/adr/adr-0053-no-shadowing-global-attributes.md)
|
|
484
|
+
rules that no component-local attribute may shadow a global one; this is the first instance
|
|
485
|
+
resolved under that policy (gh#1299).
|
|
486
|
+
|
|
487
|
+
**No deprecation alias.** Keeping `margin` as an alias on `qr-code-ui` would preserve the exact
|
|
488
|
+
collision the rename exists to remove — `margin` on `qr-code-ui` reverts to meaning what it
|
|
489
|
+
means everywhere: the global Scale attribute.
|
|
490
|
+
|
|
491
|
+
### Mechanical sweep
|
|
492
|
+
|
|
493
|
+
```bash
|
|
494
|
+
git grep -nE '<qr-code-ui[^>]*\smargin='
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Every hit intending the QR quiet zone becomes `quiet-zone`:
|
|
498
|
+
|
|
499
|
+
```html
|
|
500
|
+
<!-- before --> <qr-code-ui value="…" margin="4"></qr-code-ui>
|
|
501
|
+
<!-- after --> <qr-code-ui value="…" quiet-zone="4"></qr-code-ui>
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
**Programmatic setters** (JS render paths — the grep above misses these):
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
git grep -rnE "setAttribute\('margin', |\.margin\s*="
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
Filter to `qr-code-ui` hosts only — `margin` is a legitimate global attribute on every other
|
|
511
|
+
element, so only rewrite a hit that is actually a `<qr-code-ui>` reference:
|
|
512
|
+
`setAttribute('margin', …)` → `setAttribute('quiet-zone', …)`; `el.margin = …` → `el.quietZone
|
|
513
|
+
= …`.
|
|
514
|
+
|
|
515
|
+
### Verify
|
|
516
|
+
|
|
517
|
+
```bash
|
|
518
|
+
git grep -nE '<qr-code-ui[^>]*\smargin=' # must be 0
|
|
519
|
+
npm run check # in-repo consumers; downstream: your app's build
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Upcoming — leading-scale consolidation (ADR-0052)
|
|
525
|
+
|
|
526
|
+
**BREAKING, no aliases, ships in `0.8.40`.** [ADR-0052](../../docs/adr/adr-0052-leading-scale-consolidation.md)
|
|
527
|
+
retires the legacy `--a-leading-*` family. `--a-font-leading-*` is now the
|
|
528
|
+
single canonical line-height scale.
|
|
529
|
+
|
|
530
|
+
**Why:** two leading-token families coexisted in `scale.css` with the same
|
|
531
|
+
step names resolving to *different* values (`--a-leading-snug` = `1.3` vs.
|
|
532
|
+
`--a-font-leading-snug` = `1.2`). A component author reaching for a leading
|
|
533
|
+
token had no obviously-correct choice — which is why a corpus-wide sweep
|
|
534
|
+
(gh#1298) found 55 component files reaching for a bare numeric literal
|
|
535
|
+
instead of either family. `--a-font-leading-*` is what the L2 role layer
|
|
536
|
+
already consumes and its shape (tightening as size grows) is the design
|
|
537
|
+
intent on record. One step closes its only gap: `--a-font-leading-none: 1`.
|
|
538
|
+
|
|
539
|
+
**No value-preserving aliases.** `snug`/`normal` name different values
|
|
540
|
+
across the two families — aliasing one name to the other would silently
|
|
541
|
+
restyle every consumer of the alias. Replacement table (value-nearest, not
|
|
542
|
+
name-preserving):
|
|
543
|
+
|
|
544
|
+
| Removed | Value | Replacement | Value |
|
|
545
|
+
|---|---|---|---|
|
|
546
|
+
| `--a-leading-none` | `1` | `--a-font-leading-none` | `1` |
|
|
547
|
+
| `--a-leading-tight` | `1.2` | `--a-font-leading-snug` | `1.2` |
|
|
548
|
+
| `--a-leading-snug` | `1.3` | `--a-font-leading-normal` | `1.35` |
|
|
549
|
+
| `--a-leading-normal` | `1.5` | `--a-font-leading-relaxed` | `1.5` |
|
|
550
|
+
|
|
551
|
+
A surviving `var(--a-leading-*)` reference goes invalid-at-computed-value-time
|
|
552
|
+
→ inherit (same failure shape as the `--a-font` alias removal in `0.8.23`).
|
|
553
|
+
|
|
554
|
+
### The same sweep also tokenized every other hardcoded typography literal
|
|
555
|
+
|
|
556
|
+
Beyond the legacy family, gh#1298's corpus sweep found — and tokenized —
|
|
557
|
+
every bare numeric `line-height`, `em`-literal `letter-spacing`, and numeric
|
|
558
|
+
`font-weight` in `packages/web-components/components/*/*.css`:
|
|
559
|
+
|
|
560
|
+
- **`line-height`** — mapped to the nearest `--a-font-leading-*` step. Both
|
|
561
|
+
`1.3` and `1.4` map to `--a-font-leading-normal` (`1.35`) — no new step was
|
|
562
|
+
minted (at the 12–14px sizes where these values appeared, ±0.05
|
|
563
|
+
line-height is below visual significance). A handful of `1.4` hits on
|
|
564
|
+
genuinely multi-line body/description copy were mapped up to
|
|
565
|
+
`--a-font-leading-relaxed` (`1.5`) instead, case-by-case — see the sweep
|
|
566
|
+
PR description for the enumerated list. `line-height: 0` (the
|
|
567
|
+
icon/line-box-collapse idiom used by `icon.css`, `swatch.css`,
|
|
568
|
+
`qr-code.css`, etc.) is **not** a typographic leading value and was left
|
|
569
|
+
untouched.
|
|
570
|
+
- **`letter-spacing`** — mapped to the nearest `--a-font-tracking-*` step;
|
|
571
|
+
`0.05em` (off-scale) maps to `--a-font-tracking-wide` (`0.04em`), same
|
|
572
|
+
nearest-step logic as the leading family.
|
|
573
|
+
- **`font-weight`** — all hits were already on-scale and map mechanically to
|
|
574
|
+
`--a-weight-*` (`500`→medium, `600`→semibold, `700`→bold).
|
|
575
|
+
|
|
576
|
+
### A mechanized gate follows the sweep
|
|
577
|
+
|
|
578
|
+
`npm run check:typography-tokens` (wired into the `npm run check` aggregate)
|
|
579
|
+
fails on any bare numeric `line-height`, `em`-literal `letter-spacing`, or
|
|
580
|
+
numeric `font-weight` reappearing in `packages/web-components/components/*/*.css`
|
|
581
|
+
— mirroring the existing brand-chrome/foundation-layer audit gates — so the
|
|
582
|
+
parallel scale (and the literal-reaching it caused) cannot silently
|
|
583
|
+
reaccumulate.
|
|
584
|
+
|
|
585
|
+
### Mechanical sweep
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
git grep -nE -- '--a-leading-(none|tight|snug|normal)\b'
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
Apply the replacement table above at each hit — do not blind-`sed`, since
|
|
592
|
+
`snug`/`normal` map to *different* replacement names than their own name
|
|
593
|
+
would suggest.
|
|
594
|
+
|
|
595
|
+
### Verify
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
git grep -nE -- '--a-leading-(none|tight|snug|normal)\b' # must be 0
|
|
599
|
+
npm run check:typography-tokens # must exit 0
|
|
600
|
+
npm run check
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Upcoming — `toggle-option-ui` drops the legacy `data-selected` stamp (`0.8.40`, ADR-0056)
|
|
606
|
+
|
|
607
|
+
**BREAKING, no deprecation alias.** [ADR-0056](../../docs/adr/adr-0056-selection-item-selected-convention.md)'s
|
|
608
|
+
breaking half removes `<toggle-group-ui>`'s legacy `data-selected` attribute
|
|
609
|
+
stamp on its `<toggle-option-ui>` children. The declared, reflected `selected`
|
|
610
|
+
prop (shipped additively in `0.8.39`) is now the *only* current-state surface
|
|
611
|
+
— matching `<segment-ui>`'s existing convention.
|
|
612
|
+
|
|
613
|
+
**Migration:** any external CSS or script targeting `[data-selected]` on
|
|
614
|
+
`toggle-option-ui` must move to `[selected]` — same semantics, same timing,
|
|
615
|
+
just the attribute name. `toggle-group.css` itself already styled
|
|
616
|
+
`[selected]`; the removed stamp was a parallel, undocumented hook with no
|
|
617
|
+
declared API surface (invisible to the yaml SoT, the catalog, and the A2UI
|
|
618
|
+
grammar).
|
|
619
|
+
|
|
620
|
+
```bash
|
|
621
|
+
git grep -n "data-selected" -- '*.css' '*.js' '*.html' | grep -i toggle # must be 0
|
|
622
|
+
npm run check
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
---
|
|
626
|
+
|
|
386
627
|
## Migrating to `@adia-ai/*@v0.8.23` (2026-07-30)
|
|
387
628
|
|
|
388
629
|
- **Removed: the `--a-font` alias** (pre-ADR-0035 name, DEPRECATED since the 0.8.x line). Any surviving `font-family: var(--a-font)` goes invalid-at-computed-value-time → `inherit` → UA **serif** — the visible symptom is Times-faced labels on an otherwise-correct page.
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
display: grid;
|
|
172
172
|
grid-template-columns: subgrid;
|
|
173
173
|
align-items: center;
|
|
174
|
-
line-height:
|
|
174
|
+
line-height: var(--a-font-leading-relaxed);
|
|
175
175
|
color: var(--agent-reasoning-fg-muted);
|
|
176
176
|
animation: _ar-fade var(--agent-reasoning-duration) var(--agent-reasoning-easing);
|
|
177
177
|
}
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
font-size: var(--agent-reasoning-font);
|
|
200
200
|
color: var(--agent-reasoning-fg-subtle);
|
|
201
201
|
text-transform: uppercase;
|
|
202
|
-
letter-spacing:
|
|
202
|
+
letter-spacing: var(--a-font-tracking-wide);
|
|
203
203
|
font-weight: var(--agent-reasoning-weight-heading);
|
|
204
204
|
}
|
|
205
205
|
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
[data-trace-header] {
|
|
168
168
|
font-size: calc(var(--agent-trace-font) * 0.85);
|
|
169
169
|
text-transform: uppercase;
|
|
170
|
-
letter-spacing:
|
|
170
|
+
letter-spacing: var(--a-font-tracking-wider);
|
|
171
171
|
font-weight: var(--a-weight-medium);
|
|
172
172
|
color: var(--agent-trace-fg-subtle);
|
|
173
173
|
}
|
|
@@ -289,7 +289,7 @@
|
|
|
289
289
|
font-size: calc(var(--agent-trace-label-font) * 0.85);
|
|
290
290
|
font-weight: var(--a-weight-medium);
|
|
291
291
|
text-transform: uppercase;
|
|
292
|
-
letter-spacing:
|
|
292
|
+
letter-spacing: var(--a-font-tracking-wider);
|
|
293
293
|
padding-block-end: var(--a-space-1);
|
|
294
294
|
}
|
|
295
295
|
|
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
grid-template-columns: 1em 1fr;
|
|
302
302
|
column-gap: var(--agent-trace-inline-gap);
|
|
303
303
|
align-items: baseline;
|
|
304
|
-
line-height:
|
|
304
|
+
line-height: var(--a-font-leading-relaxed);
|
|
305
305
|
font-size: var(--agent-trace-font);
|
|
306
306
|
color: var(--agent-trace-fg);
|
|
307
307
|
}
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
:scope[pattern="dunning"] [data-dunning-amount] {
|
|
208
208
|
font-family: var(--alert-amount-font);
|
|
209
209
|
font-variant-numeric: tabular-nums;
|
|
210
|
-
font-weight:
|
|
210
|
+
font-weight: var(--a-weight-semibold);
|
|
211
211
|
/* Inherit color from the variant; tabular-nums + monospace make
|
|
212
212
|
the amount the scannable focal datum. */
|
|
213
213
|
}
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
font-family: var(--badge-font-family);
|
|
90
90
|
font-size: var(--badge-font-size);
|
|
91
91
|
font-weight: var(--badge-weight);
|
|
92
|
-
line-height:
|
|
92
|
+
line-height: var(--a-font-leading-none);
|
|
93
93
|
/* ── Register (issue 845) — uppercase + tracking + tabular numerals is the
|
|
94
94
|
badge/tag differentiator now that geometry is shared (see the
|
|
95
95
|
--badge-radius note above). Tag stays proportional sentence-case at
|
|
@@ -89,10 +89,11 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
|
|
|
89
89
|
blocks), but the label's ::after clips to its own line box, so
|
|
90
90
|
inheriting 1 makes half-leading negative and shears descenders
|
|
91
91
|
(g/j/p/q/y, parentheses) by ~0.93px at the default size — gh#906.
|
|
92
|
-
|
|
92
|
+
Normal (1.35) contains the font's content box at every [size]; the
|
|
93
93
|
precedent is stat.css:174,198 setting leading on the truncating
|
|
94
|
-
box rather than on the component root.
|
|
95
|
-
|
|
94
|
+
box rather than on the component root. Value-nearest migration from
|
|
95
|
+
the retired --a-leading-snug (1.3) — ADR-0052. */
|
|
96
|
+
--button-label-line-height: var(--a-font-leading-normal);
|
|
96
97
|
--button-gap: var(--a-space-1);
|
|
97
98
|
--button-bg-hover: var(--a-bg-strong); /* neutral fill → neutral -strong surface on hover */
|
|
98
99
|
--button-fg-hover: var(--a-ui-text-hover);
|
|
@@ -160,7 +161,7 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
|
|
|
160
161
|
font-family: var(--button-font-family);
|
|
161
162
|
font-size: var(--button-font-size);
|
|
162
163
|
font-weight: var(--button-font-weight);
|
|
163
|
-
line-height:
|
|
164
|
+
line-height: var(--a-font-leading-none);
|
|
164
165
|
cursor: pointer;
|
|
165
166
|
user-select: none;
|
|
166
167
|
transition:
|
|
@@ -211,7 +212,7 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
|
|
|
211
212
|
border: 1px solid var(--button-trailing-border);
|
|
212
213
|
border-radius: var(--button-trailing-radius);
|
|
213
214
|
padding: 0 var(--button-trailing-px);
|
|
214
|
-
line-height:
|
|
215
|
+
line-height: var(--a-font-leading-none);
|
|
215
216
|
/* Recolor a <kbd-ui slot="trailing"> pill via kbd's OWN tokens so it tracks
|
|
216
217
|
the button label color on every variant (primary white, ghost subtle,
|
|
217
218
|
colored fills). kbd-ui's `:scope { color: var(--kbd-fg) }` wins over the
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
border-radius: var(--calendar-picker-trigger-radius);
|
|
142
142
|
background: var(--calendar-picker-trigger-bg);
|
|
143
143
|
color: var(--calendar-picker-trigger-fg);
|
|
144
|
-
line-height:
|
|
144
|
+
line-height: var(--a-font-leading-none);
|
|
145
145
|
cursor: pointer;
|
|
146
146
|
transition:
|
|
147
147
|
border-color var(--calendar-picker-duration) var(--calendar-picker-easing),
|
|
@@ -178,7 +178,10 @@
|
|
|
178
178
|
|
|
179
179
|
[slot="caret"] {
|
|
180
180
|
flex-shrink: 0;
|
|
181
|
-
|
|
181
|
+
/* Universal caret size (gh#1314 sweep) — was riding the trigger's
|
|
182
|
+
font-size instead of the shared --a-caret-size token select-ui's
|
|
183
|
+
trigger caret already reads. */
|
|
184
|
+
--a-icon-size: var(--a-caret-size);
|
|
182
185
|
}
|
|
183
186
|
}
|
|
184
187
|
|
package/components/card/card.css
CHANGED
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
& > header > :is(text-ui[variant="display"], text-ui[variant="title"], text-ui[variant="heading"], text-ui[variant="subsection"]):not([slot]),
|
|
272
272
|
& > header > [slot="heading"] :is(h1, h2, h3, h4, h5, h6) {
|
|
273
273
|
grid-row: 1;
|
|
274
|
-
line-height:
|
|
274
|
+
line-height: var(--a-font-leading-normal);
|
|
275
275
|
margin: 0;
|
|
276
276
|
}
|
|
277
277
|
/* Heading slot is a flex container — can hold title + inline badges/metadata.
|
|
@@ -304,7 +304,7 @@
|
|
|
304
304
|
& > header > :is(text-ui[variant="body"], text-ui[variant="caption"]):not([slot]) {
|
|
305
305
|
grid-row: 2;
|
|
306
306
|
grid-column: 1 / -1;
|
|
307
|
-
line-height:
|
|
307
|
+
line-height: var(--a-font-leading-relaxed);
|
|
308
308
|
margin: 0;
|
|
309
309
|
}
|
|
310
310
|
& > header:has(> [slot="icon"]) > :is([slot="description"], p, small) { grid-column: 2 / -1; }
|
|
@@ -489,7 +489,7 @@
|
|
|
489
489
|
font-size: var(--card-font-size);
|
|
490
490
|
font-weight: var(--a-weight-medium);
|
|
491
491
|
color: var(--card-heading-fg);
|
|
492
|
-
line-height:
|
|
492
|
+
line-height: var(--a-font-leading-normal);
|
|
493
493
|
margin: 0;
|
|
494
494
|
flex: 0 0 auto;
|
|
495
495
|
}
|
|
@@ -53,6 +53,11 @@
|
|
|
53
53
|
"component": {
|
|
54
54
|
"const": "Chart"
|
|
55
55
|
},
|
|
56
|
+
"cornerRadius": {
|
|
57
|
+
"description": "Bar corner radius in px (null = let CSS tokens decide)",
|
|
58
|
+
"type": "number",
|
|
59
|
+
"default": null
|
|
60
|
+
},
|
|
56
61
|
"data": {
|
|
57
62
|
"description": "JS property (set programmatically — `el.data = [...]`). An array of plain objects; each object's keys are named by the `x` and `y` attributes — e.g. `<chart-ui x=\"month\" y=\"revenue\">` consumes `[{month:'Jan', revenue:3200}, {month:'Feb', revenue:4100}]`. The Chart.js `{labels, datasets}` envelope is NOT chart-ui's API — passing it (or any non-array value) renders an empty chart. May also be supplied declaratively as a JSON-array `data=\"[…]\"` attribute, hydrated once at connect. Custom accessor on the element class, not a reflected attribute.",
|
|
58
63
|
"$ref": "common_types.json#/$defs/DynamicObjectList"
|
|
@@ -99,11 +104,6 @@
|
|
|
99
104
|
"type": "boolean",
|
|
100
105
|
"default": false
|
|
101
106
|
},
|
|
102
|
-
"radius": {
|
|
103
|
-
"description": "Bar corner radius (null = let CSS tokens decide)",
|
|
104
|
-
"type": "number",
|
|
105
|
-
"default": null
|
|
106
|
-
},
|
|
107
107
|
"seriesEmphasis": {
|
|
108
108
|
"description": "Multi-line only. Names one series key (matching a `y` key) to render at full strength — area fill + full-opacity line. Every other series drops its area fill and renders line-only at --chart-deemphasized-opacity. Empty (default) applies full treatment to every series, unchanged from pre-gh#561 behavior.",
|
|
109
109
|
"type": "string",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* color — accent/success/warning/danger/info
|
|
26
26
|
* hide-grid — hide gridlines
|
|
27
27
|
* hide-values — hide value labels
|
|
28
|
-
* radius
|
|
28
|
+
* corner-radius — bar corner radius in px (default: null, falls back to --a-radius)
|
|
29
29
|
* dots — line/multi-line marker visibility: all|none|hover|last (default: all)
|
|
30
30
|
* series-emphasis — multi-line: series key that keeps full area+line treatment; others render line-only, dimmed
|
|
31
31
|
*
|
|
@@ -219,7 +219,7 @@ export class UIChart extends UIElement {
|
|
|
219
219
|
color: { type: String, default: '', reflect: true },
|
|
220
220
|
hideGrid: { type: Boolean, default: false, reflect: true, attribute: 'hide-grid' },
|
|
221
221
|
hideValues: { type: Boolean, default: false, reflect: true, attribute: 'hide-values' },
|
|
222
|
-
|
|
222
|
+
cornerRadius: { type: Number, default: null, reflect: true, attribute: 'corner-radius' },
|
|
223
223
|
smooth: { type: Number, default: 0.4, reflect: true },
|
|
224
224
|
size: { type: String, default: '', reflect: true },
|
|
225
225
|
format: { type: String, default: 'abbr', reflect: true },
|
|
@@ -255,11 +255,11 @@ export class UIChart extends UIElement {
|
|
|
255
255
|
re-render without a full DOM query. */
|
|
256
256
|
#activeDotEl = null;
|
|
257
257
|
|
|
258
|
-
/** Resolves the corner radius: the `
|
|
258
|
+
/** Resolves the corner radius: the `cornerRadius` prop if explicitly set,
|
|
259
259
|
* otherwise `--a-radius` from the host's computed style. Falls back
|
|
260
260
|
* to 6 if the token is unset (should not happen in practice). */
|
|
261
261
|
#resolveRadius() {
|
|
262
|
-
if (this.
|
|
262
|
+
if (this.cornerRadius != null) return this.cornerRadius;
|
|
263
263
|
const val = getComputedStyle(this).getPropertyValue('--a-radius').trim();
|
|
264
264
|
const parsed = parseFloat(val);
|
|
265
265
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 6;
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
|
|
177
177
|
[data-value] {
|
|
178
178
|
font-size: var(--chart-font-size);
|
|
179
|
-
font-weight:
|
|
179
|
+
font-weight: var(--a-weight-semibold);
|
|
180
180
|
fill: var(--chart-value);
|
|
181
181
|
font-family: var(--chart-font);
|
|
182
182
|
}
|
|
@@ -265,7 +265,7 @@
|
|
|
265
265
|
[data-avg-label] {
|
|
266
266
|
fill: var(--chart-avg);
|
|
267
267
|
font-family: var(--chart-font);
|
|
268
|
-
font-weight:
|
|
268
|
+
font-weight: var(--a-weight-semibold);
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
/* ── Radar ── */
|
|
@@ -388,7 +388,7 @@
|
|
|
388
388
|
/* ── Donut center text ── */
|
|
389
389
|
|
|
390
390
|
[data-donut-total] {
|
|
391
|
-
font-weight:
|
|
391
|
+
font-weight: var(--a-weight-bold);
|
|
392
392
|
fill: var(--chart-fg);
|
|
393
393
|
font-family: var(--chart-font);
|
|
394
394
|
/* font-size set by JS on the element — scales with donut radius */
|
|
@@ -719,7 +719,7 @@
|
|
|
719
719
|
color: var(--chart-tooltip-fg);
|
|
720
720
|
font-family: var(--a-font-family);
|
|
721
721
|
font-size: var(--a-ui-sm);
|
|
722
|
-
line-height:
|
|
722
|
+
line-height: var(--a-font-leading-normal);
|
|
723
723
|
border: none;
|
|
724
724
|
border-radius: var(--chart-tooltip-radius);
|
|
725
725
|
box-shadow: var(--chart-tooltip-shadow);
|
|
@@ -741,11 +741,11 @@
|
|
|
741
741
|
font-size: var(--a-ui-tiny);
|
|
742
742
|
opacity: 0.75;
|
|
743
743
|
text-transform: uppercase;
|
|
744
|
-
letter-spacing:
|
|
744
|
+
letter-spacing: var(--a-font-tracking-wide);
|
|
745
745
|
}
|
|
746
746
|
|
|
747
747
|
.chart-tooltip-popup [data-tip-role="label"] {
|
|
748
|
-
font-weight:
|
|
748
|
+
font-weight: var(--a-weight-medium);
|
|
749
749
|
}
|
|
750
750
|
|
|
751
751
|
.chart-tooltip-popup [data-tip-role="value"] {
|
|
@@ -22,6 +22,8 @@ export class UIChart extends UIElement {
|
|
|
22
22
|
type: 'bar' | 'line' | 'pie' | 'donut' | 'radar' | 'sparkline' | 'segments' | 'area' | 'scatter' | 'radial-bar' | 'gauge' | 'stacked-bar' | 'grouped-bar' | 'multi-line' | 'funnel' | 'treemap' | 'sankey' | 'composed';
|
|
23
23
|
/** Color scheme */
|
|
24
24
|
color: 'accent' | 'success' | 'warning' | 'danger' | 'info';
|
|
25
|
+
/** Bar corner radius in px (null = let CSS tokens decide) */
|
|
26
|
+
cornerRadius: number;
|
|
25
27
|
/** JS property (set programmatically — `el.data = [...]`). An array of plain objects; each object's keys are named by the `x` and `y` attributes — e.g. `<chart-ui x="month" y="revenue">` consumes `[{month:'Jan', revenue:3200}, {month:'Feb', revenue:4100}]`. The Chart.js `{labels, datasets}` envelope is NOT chart-ui's API — passing it (or any non-array value) renders an empty chart. May also be supplied declaratively as a JSON-array `data="[…]"` attribute, hydrated once at connect. Custom accessor on the element class, not a reflected attribute. */
|
|
26
28
|
data: string;
|
|
27
29
|
/** Marker (dot) visibility for line and multi-line series. `all` draws a circle[data-dot] on every datum (default — matches pre-gh#561 behavior). `none` hides all dots so a dense series reads as a clean line. `hover` shows only the currently-hovered datum's dot. `last` shows only the terminal point per series (sparkline convention). Tooltip hit targets ([data-hit]) are a separate always-rendered layer — every mode keeps hover/click working along the whole line. */
|
|
@@ -36,8 +38,6 @@ export class UIChart extends UIElement {
|
|
|
36
38
|
hideValues: boolean;
|
|
37
39
|
/** Show a skeleton placeholder instead of the chart body. Set to true while data is being fetched; clear once data arrives. Preserves the element's aspect-ratio dimensions so the skeleton occupies the same space the chart will fill. Parity with stat-ui[loading] and table-ui[loading] (§FB-12, v0.6.27). */
|
|
38
40
|
loading: boolean;
|
|
39
|
-
/** Bar corner radius (null = let CSS tokens decide) */
|
|
40
|
-
radius: number;
|
|
41
41
|
/** Multi-line only. Names one series key (matching a `y` key) to render at full strength — area fill + full-opacity line. Every other series drops its area fill and renders line-only at --chart-deemphasized-opacity. Empty (default) applies full treatment to every series, unchanged from pre-gh#561 behavior. */
|
|
42
42
|
seriesEmphasis: string;
|
|
43
43
|
/** Chart size */
|