@adia-ai/web-components 0.8.22 → 0.8.23
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 +45 -0
- package/MIGRATION.md +9 -0
- package/components/agent-trace/agent-trace.js +4 -1
- package/components/alert/alert.a2ui.json +1 -1
- package/components/alert/alert.css +44 -5
- package/components/alert/alert.yaml +8 -4
- package/components/canvas/canvas.js +4 -1
- package/components/chat-thread/chat-input.js +4 -1
- package/components/code/code.css +29 -26
- package/components/description-list/description-list.css +9 -0
- package/components/drawer/drawer.css +16 -0
- package/components/field/field.css +4 -1
- package/components/list/list.css +12 -1
- package/components/nav-group/nav-group.class.js +45 -2
- package/components/nav-group/nav-group.css +11 -2
- package/components/progress-row/progress-row.class.js +10 -2
- package/components/richtext/richtext.css +7 -0
- package/components/select/select.a2ui.json +5 -0
- package/components/select/select.class.js +25 -6
- package/components/select/select.yaml +13 -0
- package/components/stat/stat.js +4 -1
- package/components/stepper/stepper.css +25 -20
- package/components/table/table.a2ui.json +15 -1
- package/components/table/table.class.js +14 -1
- package/components/table/table.css +68 -3
- package/components/table/table.d.ts +5 -1
- package/components/table/table.yaml +34 -1
- package/components/tabs/tab.js +4 -1
- package/components/tag/tag.css +15 -9
- package/core/provider.js +5 -1
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +1 -1
- package/dist/scale.min.css +1 -1
- package/dist/scale.sheet.js +1 -1
- package/dist/theme-provider.min.js +2 -2
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +93 -93
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -1
- package/patterns/access-requests/access-requests.examples.html +12 -3
- package/patterns/admin-keys-and-export/admin-keys-and-export.examples.html +20 -5
- package/patterns/agent-cost/agent-cost.examples.html +12 -3
- package/patterns/agent-memory/agent-memory.examples.html +12 -3
- package/patterns/agent-prompt-library/agent-prompt-library.examples.html +12 -3
- package/patterns/agent-tool-call/agent-tool-call.examples.html +16 -4
- package/patterns/alert-dialog/alert-dialog.examples.html +12 -3
- package/patterns/app-nav/app-nav.examples.html +36 -9
- package/patterns/approvals/approvals.examples.html +14 -10
- package/patterns/audit-log/audit-log.examples.html +5 -2
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.html +210 -32
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.js +83 -4
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.html +68 -0
- package/patterns/changelog-feed/changelog-feed.examples.html +4 -1
- package/patterns/chart-in-card/chart-in-card.examples.html +28 -7
- package/patterns/comments-and-collaboration/comments-and-collaboration.examples.html +20 -5
- package/patterns/conversion-funnel/conversion-funnel.examples.html +24 -15
- package/patterns/data-tables-inline-edit-and-tree/data-tables-inline-edit-and-tree.examples.html +15 -6
- package/patterns/diff-review/diff-review.examples.html +12 -3
- package/patterns/export-flow/export-flow.examples.html +12 -3
- package/patterns/filter-bar/filter-bar.examples.html +13 -4
- package/patterns/form-drawer/form-drawer.examples.html +15 -6
- package/patterns/form-system/form-system.examples.html +4 -1
- package/patterns/forms-conditional-and-autocomplete/forms-conditional-and-autocomplete.examples.html +12 -3
- package/patterns/inline-dialog/inline-dialog.examples.html +12 -3
- package/patterns/kanban-board/kanban-board.examples.html +4 -1
- package/patterns/marketing-engagement/marketing-engagement.examples.html +24 -6
- package/patterns/notifications-bell-and-digest/notifications-bell-and-digest.examples.html +12 -3
- package/patterns/permissions-matrix/permissions-matrix.examples.html +9 -3
- package/patterns/permissions-role-picker/permissions-role-picker.examples.html +8 -2
- package/patterns/permissions-sharing/permissions-sharing.examples.html +12 -3
- package/patterns/profile-public-and-verification/profile-public-and-verification.examples.html +16 -4
- package/patterns/record-detail-drawer/record-detail-drawer.examples.html +10 -4
- package/patterns/retention-cohort/retention-cohort.examples.html +15 -6
- package/patterns/search-discovery/search-discovery.examples.html +16 -4
- package/patterns/system-banners/system-banners.examples.html +54 -48
- package/patterns/timezone-selector/timezone-selector.examples.html +8 -2
- package/patterns/timezone-selector/timezone-selector.examples.js +3 -1
- package/patterns/wizard-drawer/wizard-drawer.examples.html +25 -23
- package/patterns/wizard-drawer/wizard-drawer.examples.js +12 -1
- package/styles/foundation/radius.css +2 -2
- package/styles/scale.css +2 -2
- package/styles/type/scale.css +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
2
|
|
|
3
|
+
## [0.8.23] — 2026-07-30
|
|
4
|
+
|
|
5
|
+
### Removed
|
|
6
|
+
- **BREAKING — the `--a-font` back-compat alias** (operator ruling 2026-07-30; ships in **0.8.23** as an operator-ruled PATCH exception to the removals-are-MINOR convention). The pre-ADR-0035 name is gone from `type/scale.css`; surviving `var(--a-font)` references resolve to UA serif. Consumer sweep is mechanical (`var(--a-font)` → `var(--a-font-family)`); `audit-font-family-floor` Check B and the plugin lint hooks flag any stragglers. MIGRATION GUIDE §v0.8.23.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- **`richtext-ui` lists inherit the body font spec** (gh#546, operator chat screenshot). `p` was pinned to `--richtext-body-size` while `ul`/`li` carried no font rule and inherited the HOST page's larger base — chat-rendered bullet items read bigger than the paragraph beside them. The body size + leading now sit once on `[data-richtext-body]` and everything inherits (headings/code still override). Probe: p and li both 14px inside an 18px host.
|
|
10
|
+
- **Deployed-site freeze class eliminated** (gh#534, operator repro + live-browser diagnosis). Cold loads of the deployed site could stall the ~250-file raw module graph on one hung fetch, leaving the page as un-upgraded markup — visible, scrollable, zero interactivity, no error. Two-part fix: (1) on https (or `?force-bundle`) the prebuilt everything-bundle loads in PARALLEL with the module graph, so element registration rides one request; every registration is now `defineIfFree` (22 bare `customElements.define` calls guarded across components + modules — the parallel load surfaced each collision); (2) an 8s registration watchdog surfaces a plain-DOM reload prompt instead of an indefinite freeze. Probe-verified: three heavy routes clean under bundle+graph with zero collisions, dev path untouched, and a stalled-graph negative control trips the banner.
|
|
11
|
+
- **A2UI runtime registry gains `ToolbarGroup → toolbar-group-ui`** (gh#535, operator screenshot). The missing entry made toolbar-group an unknown tag, so the docs transpiler Column-wrapped every toolbar group — the floating bulk-action bar rendered as vertical col-ui stacks on its site route. Rows regenerated; surface-verified warm (groups render, bars 67–75px, main thread responsive — the earlier freeze signal was cold-Vite first-compile noise, not a loop).
|
|
12
|
+
- **`table-ui` perimeter is three-sided — no top edge** (gh#537, operator report). A line above the header read as a stray divider under a card edge or empty-state; the header row's own border-bottom is the table's top structure. Sides + bottom keep the standalone silhouette; `[frameless]` unchanged.
|
|
13
|
+
- **`select-ui [searchable]` matches underscores as spaces** (gh#538) — typing "Los Angeles" now finds `America/Los_Angeles`; the timezone-selector pattern also displays humanized (de-underscored) labels while values keep exact IANA ids.
|
|
14
|
+
- **`approvals` pattern: priority tag leads the request context** (gh#539, operator ruling) — the High tag moves from the trailing action cluster to the front of the requester/department/age line; trailing cluster is Reject · Approve only.
|
|
15
|
+
- **`list-item-ui` iconless items no longer indent behind a ghost grid track** (gh#524, operator devtools screenshot). The `auto 1fr` grid charged its `column-gap` beside the empty leading track. The gap now rides the icon's own `margin-inline-end` (and the action's `margin-inline-start`); empty stamped icon spans hide. Surface-verified: Playwright measurement on /site/patterns/search-discovery — text indent 0 on iconless rows.
|
|
16
|
+
- **`select-ui [mark]` implies the no-radio menu treatment** (gh#498 REOPENED — the first fix applied `[no-radio]` to the playground switcher and closed green while the site chrome switcher kept its radios; operator caught it same-day). A mark declares an identity switcher, so the semantic attribute now carries the treatment; `[no-radio]` remains for markless menus. Surface-verified this time: Playwright probe of the site chrome `#workspace-select` — 2 rows, 0 radio indicators. Tests 38 → 39.
|
|
17
|
+
- **Nav selection icon color is one language** (gh#522, operator ruling). A nav-group containing the selected route filled its header glyph (gh#501) in plain label color — reading as unselected beside nav-item's primary accent glyph. The contains-selection state now reflects as `[data-selected-within]` (set by the gh#501 sync, observer-safe), and the header icon paints `--nav-group-icon-fg-selected` (default `--md-sys-color-primary`, one token language with `--nav-item-accent`) whenever the group is selected or contains the selection. Sub-items keep their own accent-bar system. Tests 9 → 10.
|
|
18
|
+
- **`patterns/wizard-drawer` works on the site route** (gh#506, operator report). The open/cancel affordances were inline `onclick` handlers, which the site's A2UI render path does not execute — the drawer could never open on /site/patterns/wizard-drawer, so the whole three-step use case was dead there. All interactivity now lives in the pattern's `examples.js` setup module (which the route does run); verified end-to-end in a real browser: trigger opens → Next/Back swap panels with the stepper → Create closes.
|
|
19
|
+
- **`tag-ui` no longer top-pins in table cells** (gh#503, adia-v2 report — measured −34px off-center). The TKT-0021 guard `align-self: start` acted on the PARENT's cross axis: correct in a col-ui stack, but vertical in every flex-row parent (table cells, row-ui, toolbars). Re-cut as `width: fit-content` — defeats column-stretch identically (stretch applies only at auto cross size), while row parents' `align-items: center` regains vertical control. Tag-only; badge/button never carried the rule.
|
|
20
|
+
- **`alert-ui` variant icons clear legibility on their own tinted surface** (gh#507, operator screenshot). Icon fg moves from `--a-<family>-strong` (an on-SURFACE color, near-invisible against the family's dark-scheme container tint) to the gh#434 gate-proven `--md-sys-color-<family>-on-<family>-container` role (dark leg measured 5.6–9.2:1).
|
|
21
|
+
|
|
22
|
+
- **`nav-group-ui` header glyph fills when a CHILD is selected** (gh#501, operator report). gh#459 ruled "the group CONTAINING the selected route fills" but relied on consumers setting `[selected]` on the group; a MutationObserver (subtree, `[selected]` filter + childList) now makes it self-enforcing — targeted weight sync only, since a full re-render from the observer would loop on its own textContent writes. Symmetric disconnect. Tests 7 → 9.
|
|
23
|
+
- **`progress-row-ui` authored `[slot="meta"]` content survives render** (gh#502). `render()` unconditionally wrote `textContent` from the `[meta]` attr and hid the element when the attr was empty, so authored meta content (text + a trailing delta badge) was wiped — the slot was effectively attr-only. The attr still owns the text when set; absent, authored children are kept and only a genuinely empty meta hides. New test file, 4 passing. The `conversion-funnel` pattern's step-over-step variant now rides its delta badges inside the meta slot instead of a sibling column misaligned against the row.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **`table-ui [frameless]` + the `--table-perimeter` token split** (gh#511, adia-v2 console tables). The 1px perimeter and the row dividers both read `--table-border` (TKT-0026), so a card-composed table always double-bordered — the card's rounded outline plus the table's square frame — and consumers couldn't drop one without the other. The perimeter now reads its own `--table-perimeter` (default: `var(--table-border)` — standalone tables unchanged); `[frameless]` blanks just that token. Pattern rule: inside `card-ui`, set frameless — the container owns the frame. Tests 45 → 49.
|
|
27
|
+
- **`patterns/bulk-action-toolbar`: a floating, bottom-anchored variant** (gh#494, operator ruling — adia-v2 evidence-console + independent kit-side report, ADIA2-7028). Long/paginated tables scroll the top-swap bar out of view exactly when a mid-scroll selection needs it; the floating variant is a card-like elevated bar (`card-ui[elevation="3"]`) that rises `position: sticky` from the bottom of the table's own scroll container — never the browser viewport — driven by `table-ui`'s existing `select` event. Anatomy: `aria-live="polite"` selection count, an optional per-flow controls slot, actions with destructive last, an explicit Clear. Composed entirely from existing primitives (`card-ui` + `toolbar-ui` + `toolbar-group-ui`) — the anchored-surface primitive filed as gh#495 was not needed. The pattern doc now states which variant to pick and why (floating default once a table runs taller than ~one viewport). The top-swap variant stays valid and unchanged in shape; fixed alongside it: a real defect where its trailing action (Delete) silently spilled into an unreachable "more" menu (a flex-grow spacer inflates `toolbar-ui`'s own overflow-width measurement) — both variants now push their action group right via `toolbar-group-ui` + `align="space-between"` instead.
|
|
28
|
+
- **`table-ui [valign]` — host + per-column vertical alignment** (gh#505, adia-v2 evidence-sources/organizations console tables). Every body-cell `align-items` was unconditionally `center`, which floats single-line neighbors (dates, status chips) at a different vertical center than a tall/wrapped primary cell — no way to opt into the Gmail/Linear/Notion "top-align, shared first-line scan anchor" convention. `<table-ui valign="top">` flips body cells to `align-items: flex-start` (default stays `center` — zero behavioral change for existing consumers); `columns[].valign` (or `<col-def valign="…">`) overrides the host per column, e.g. a `valign="center"` checkbox column inside a `valign="top"` table. Header cells and the structural checkbox/expand-toggle columns always stay centered regardless — they're single-line/fixed-size by contract, immune to the new token. New `--table-valign` mode token, added to the Sanctioned Mode Attributes table (`component-token-contract.md`). Tests 31 → 45.
|
|
29
|
+
- **`alert-ui` sectioned content anatomy** (gh#507) — card-ui's rhythm inside the content slot: semantic `<header>`/`<section>`/`<footer>` children of the slotted wrapper, component-owned gaps (`--alert-section-gap`, `--alert-footer-gap`), footer right-aligned with its own step of air. Free-form content is untouched (the column engages only when structural children are present). The system-banners pattern's six banners now compose this way.
|
|
30
|
+
- **`select-ui [no-radio]`** (gh#498, operator report). Opt-out for the single-select radio indicator on menu-shaped switchers — workspace/user identity menus — where the trigger already shows the committed value and a per-row radio reads as redundant. Drops only the dot: rows keep `[data-single-option]` layout and `aria-selected` (trigger + selected-row weight carry the signal); no effect under `[multiple]`. Applied to the admin-shell playground's workspace switcher, the reported surface. Tests 36 → 38.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **Carded tables adopt `[frameless]`** (gh#500 resolution) — the 11 card-composed `table-ui` instances across six patterns drop their doubled perimeter per the gh#511 rule: inside card-ui, the container owns the frame. Standalone tables unchanged.
|
|
34
|
+
- **Default radius band: 6px–14px** (operator ruling 2026-07-30). `--a-radius-min` 0.25rem → 0.375rem, `--a-radius-max` 1.25rem → 0.875rem in `foundation/radius.css` and its `scale.css` ui-md byte-copy — every `--a-radius-xs/sm/md/lg` step re-clamps into the new band kit-wide. The ui-sm/ui-lg and content registers keep their own authored bands.
|
|
35
|
+
- **`drawer-ui`: a leading `stepper-ui` in the body is sticky wizard chrome** (operator ruling 2026-07-30) — pins just below the sticky header on the panel's own background, padded and bled to the body edges so panels scroll cleanly beneath; `--drawer-sticky-offset` overridable for taller headers.
|
|
36
|
+
- **`stepper-ui` state system re-cut** (operator ruling 2026-07-30, with mock): completed = `primary-container` bg + `primary` glyph, transparent border; current = `primary` bg + `on-primary` glyph, transparent border; next = transparent bg, `on-surface-variant` glyph, `outline-variant` border. Labels: current `on-surface`, completed/next `on-surface-variant` (new `--stepper-item-label-fg-done` token). All existing `--stepper-*` overrides keep working — only default values moved.
|
|
37
|
+
- **`field-ui` labels read at 13-14px** (operator ruling 2026-07-30): `--field-label-size` moves `--a-ui-sm` → `--a-ui-md` (12px → 13px base register; 14px in larger registers) — labels no longer read smaller than the control text beside them.
|
|
38
|
+
- **`description-list-ui [layout="inline"]` collapses responsively** — the two-column property|value grid stacks under 480px instead of squeezing the value column; pairs with the wizard-drawer review step's new settings-style layout.
|
|
39
|
+
- **`patterns/wizard-drawer` restructured** (operator rulings): stepper moves from header chrome to the FIRST content block (`header / content (stepper) / content / footer`); the review step swaps its stacked list for `description-list-ui layout="inline"` — the responsive two-column settings layout. Anatomy sample + rules updated; browser-probe green end-to-end.
|
|
40
|
+
- **`code-ui` color tokens map directly to `--md-sys-color-*` roles** (operator ask 2026-07-30). All 25 color refs (syntax `--code-tok-*`, editor chrome, lint markers) drop the `--a-*` alias hop for the md-sys role each alias already resolved to — value-identical except `--code-tok-function`: brand has no md-sys mirror, so it moves to `--md-sys-color-tertiary-active` (the identity-adjacent family). Layout/typography/motion tokens untouched; per-instance overrides work exactly as before.
|
|
41
|
+
- **`table-ui` sort carets render larger** (gh#496, operator report). The header sort indicator (`caret-up-down` idle, `arrow-up`/`arrow-down` active) moves `--a-icon-size` 0.75em → 0.95em — ~+2px at the heading's `--a-ui-xs` size, em-based so it keeps scaling with the register. `--table-sort-*` overrides untouched.
|
|
42
|
+
|
|
43
|
+
### Maintenance
|
|
44
|
+
- **`core/` touched in this release window** (1 file(s), e.g. `core/provider.js`) — carried by the entries above.
|
|
45
|
+
- **`dist/` bundles rebuilt** in this cut's window (8 file(s)) — regenerated from the source changes described above, not independent edits.
|
|
46
|
+
- **`styles/` touched in this release window** (3 file(s), e.g. `foundation/radius.css`) — carried by the entries above.
|
|
47
|
+
|
|
3
48
|
## [0.8.22] — 2026-07-29
|
|
4
49
|
|
|
5
50
|
### Fixed
|
package/MIGRATION.md
CHANGED
|
@@ -46,12 +46,21 @@ Version cuts and migration scope:
|
|
|
46
46
|
|
|
47
47
|
- **`0.8.0`** — MINOR lockstep cut (2026-07-15). Internal ranges `^0.7.0` → `^0.8.0`. **BREAKING (3 items):** the Material color-token adoption — `--md-sys-color-*` (a static export) is now the color system's source of truth and public API. Removed: the 19 `--a-accent-*` back-compat aliases (→ `--a-primary-*`), the 189 raw per-family `--a-{family}-{0..6}-{tint-|shade-}scrim` primitives (→ the static `--md-sys-color-{family}-scrim-*` ladder), and the `primitives-accent.css` deep-import path (→ `primitives-primary.css`). **Behavioral:** the 8 named `[theme]` presets no longer re-color components (only brand hue + radius/density/shadow knobs still respond). See [§ v0.8.0 section below](#migrating-to-adia-aiv080-2026-07-15).
|
|
48
48
|
|
|
49
|
+
- **`0.8.23`** — PATCH lockstep cut (2026-07-30; operator ruling — an operator-ruled PATCH exception to the removals-are-MINOR convention). **BREAKING (1 item):** the `--a-font` back-compat alias is removed. See [§ v0.8.23 section below](#migrating-to-adia-aiv0823-2026-07-30).
|
|
50
|
+
|
|
49
51
|
- **`0.8.11`** — PATCH lockstep cut (2026-07-23). Internal ranges stay at `^0.8.0`. **BREAKING: the size model.** Every component `size` enum is now exactly `sm | md | lg`; the removed tiers (`xs`, `xl`, icon's `2xl/3xl/4xl/fill`) are served by the new ancestor **`[scale]`** context — six hand-tabled tiers (`ui-sm · ui-md · ui-lg · content-sm · content-md · content-lg`): scale picks the table, `size` picks the row. `[verse]`/`[prose]` are deprecated aliases of `ui-sm`/`content-md` (removed at v1.0). Also new: `<adia-wordmark-ui>`. See [§ v0.8.11 section below](#migrating-to-adia-aiv0811-2026-07-23).
|
|
50
52
|
|
|
51
53
|
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.
|
|
52
54
|
|
|
53
55
|
---
|
|
54
56
|
|
|
57
|
+
## Migrating to `@adia-ai/*@v0.8.23` (2026-07-30)
|
|
58
|
+
|
|
59
|
+
- **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.
|
|
60
|
+
- **Mechanical sweep:** replace `var(--a-font)` → `var(--a-font-family)` — exact match only; `--a-font-family` / `--a-font-*` names are current API and must not be touched. The kit's own sweep used `codemod-demo-host-css.mjs --token-only`, which consumers can run against their tree.
|
|
61
|
+
- **Detection:** `audit-font-family-floor.mjs` Check B flags any `var(--a-font)` usage as CRITICAL; the forge/factory lint hooks flag it at write time.
|
|
62
|
+
- The 0.8.16 font-family floors on text-bearing primitives remain, so kit components stay sans even beside a broken host declaration — only YOUR selectors referencing the dead token regress.
|
|
63
|
+
|
|
55
64
|
## Migrating to `@adia-ai/*@v0.8.11` (2026-07-23)
|
|
56
65
|
|
|
57
66
|
**PATCH lockstep cut.** Internal ranges stay at `^0.8.0`. One breaking theme: **the size model contracts to `sm | md | lg` everywhere, and an ancestor `[scale]` attribute takes over everything the extra tiers did.** `styles/scale.css` (new, opt-in like verse/prose; `dist/scale.min.css` + `dist/scale.sheet.js`) defines six explicit tiers — `ui-sm` (≡ old `[verse]`), `ui-md` (≡ base), `ui-lg`, `content-sm`, `content-md` (≡ old `[prose]`), `content-lg` — each a full hand-tabled re-declaration of the `--a-size/-inset/-gap/-radius/-icon/-caret/-toggle` families and all 13 type roles. Scale picks the table, `[size]` picks the row; an unscaled page renders byte-identically to v0.8.10.
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* trace-toggle — summary opened/closed
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
import { defineIfFree } from '../../core/register.js';
|
|
37
38
|
import { UIElement } from '../../core/element.js';
|
|
38
39
|
|
|
39
40
|
class UIAgentTrace extends UIElement {
|
|
@@ -220,5 +221,7 @@ function escapeAttr(s) {
|
|
|
220
221
|
return String(s).replace(/"/g, '"');
|
|
221
222
|
}
|
|
222
223
|
|
|
223
|
-
|
|
224
|
+
// defineIfFree (gh#534): the prod bundle + module graph load in parallel;
|
|
225
|
+
// second registration must no-op, not throw.
|
|
226
|
+
defineIfFree('agent-trace-ui', UIAgentTrace);
|
|
224
227
|
export { UIAgentTrace };
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
"description": "Close button. Stamped automatically when `closable` is set; the stamped element is `<button-ui slot=\"close\" icon=\"x\" variant=\"ghost\" size=\"sm\">`. Override by passing a custom `slot=\"close\"` button."
|
|
180
180
|
},
|
|
181
181
|
"content": {
|
|
182
|
-
"description": "Alert body. For single-line text use the `text=` attribute (alert.js stamps a `<span slot=\"content\">` automatically). For
|
|
182
|
+
"description": "Alert body. For single-line text use the `text=` attribute (alert.js stamps a `<span slot=\"content\">` automatically). For structured banners use card-ui's section rhythm INSIDE the content element (gh#507): semantic `<header>` (title), `<section>` (body), and `<footer>` (actions — right-aligned with its own step of air) children of the slotted wrapper; the component owns the gaps (`--alert-section-gap`, `--alert-footer-gap`), so spacing balances without per-banner col-ui/row-ui improvisation. Free-form content without those children lays out exactly as before."
|
|
183
183
|
},
|
|
184
184
|
"leading": {
|
|
185
185
|
"description": "Leading icon. Stamped automatically from the `icon=` attribute; consumers can override by passing a custom `<icon-ui slot=\"leading\">`."
|
|
@@ -42,33 +42,38 @@
|
|
|
42
42
|
background: var(--alert-bg);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/* ── Variants ──
|
|
45
|
+
/* ── Variants ──
|
|
46
|
+
Icon fg = the family's on-container tonal-text role (gh#507): the icon
|
|
47
|
+
sits ON the -container tint, and the gh#434 gate-proven on-container
|
|
48
|
+
stops clear AA on both legs there (dark leg measured 5.6-9.2:1). The
|
|
49
|
+
former --a-<family>-strong is an on-SURFACE color — near-invisible
|
|
50
|
+
against its own family's dark-scheme container tint. */
|
|
46
51
|
:scope[variant="info"] {
|
|
47
52
|
--alert-bg: var(--md-sys-color-info-container);
|
|
48
53
|
--alert-fg: var(--md-sys-color-info-on-surface);
|
|
49
54
|
--alert-border: var(--md-sys-color-info-outline-variant);
|
|
50
|
-
--alert-icon-fg: var(--
|
|
55
|
+
--alert-icon-fg: var(--md-sys-color-info-on-info-container);
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
:scope[variant="success"] {
|
|
54
59
|
--alert-bg: var(--md-sys-color-success-container);
|
|
55
60
|
--alert-fg: var(--md-sys-color-success-on-surface);
|
|
56
61
|
--alert-border: var(--md-sys-color-success-outline-variant);
|
|
57
|
-
--alert-icon-fg: var(--
|
|
62
|
+
--alert-icon-fg: var(--md-sys-color-success-on-success-container);
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
:scope[variant="warning"] {
|
|
61
66
|
--alert-bg: var(--md-sys-color-warning-container);
|
|
62
67
|
--alert-fg: var(--md-sys-color-warning-on-surface);
|
|
63
68
|
--alert-border: var(--md-sys-color-warning-outline-variant);
|
|
64
|
-
--alert-icon-fg: var(--
|
|
69
|
+
--alert-icon-fg: var(--md-sys-color-warning-on-warning-container);
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
:scope[variant="danger"] {
|
|
68
73
|
--alert-bg: var(--md-sys-color-danger-container);
|
|
69
74
|
--alert-fg: var(--md-sys-color-danger-on-surface);
|
|
70
75
|
--alert-border: var(--md-sys-color-danger-outline-variant);
|
|
71
|
-
--alert-icon-fg: var(--
|
|
76
|
+
--alert-icon-fg: var(--md-sys-color-danger-on-danger-container);
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
/* `muted` and `neutral` are semantic aliases of the base — same tokens
|
|
@@ -105,6 +110,40 @@
|
|
|
105
110
|
min-width: 0;
|
|
106
111
|
}
|
|
107
112
|
|
|
113
|
+
/* ── Sectioned content (gh#507) — card-ui's header/section/footer rhythm,
|
|
114
|
+
owned by the component so banner spacing stops being per-author col-ui/
|
|
115
|
+
row-ui gap improvisation. Authors write semantic children inside the
|
|
116
|
+
content slot:
|
|
117
|
+
<div slot="content">
|
|
118
|
+
<header>…title…</header>
|
|
119
|
+
<section>…body…</section>
|
|
120
|
+
<footer><button-ui …></footer>
|
|
121
|
+
</div>
|
|
122
|
+
The wrapper columnizes only when structural children are present, so
|
|
123
|
+
existing free-form content is untouched. */
|
|
124
|
+
:scope [slot="content"]:has(> header, & > section, & > footer) {
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-direction: column;
|
|
127
|
+
gap: var(--alert-section-gap, var(--a-space-1));
|
|
128
|
+
}
|
|
129
|
+
:scope [slot="content"] > header,
|
|
130
|
+
:scope [slot="content"] > section,
|
|
131
|
+
:scope [slot="content"] > footer {
|
|
132
|
+
margin: 0;
|
|
133
|
+
padding: 0;
|
|
134
|
+
}
|
|
135
|
+
:scope [slot="content"] > header {
|
|
136
|
+
font-weight: var(--a-weight-medium);
|
|
137
|
+
}
|
|
138
|
+
/* Footer = the action band: right-aligned, its own step of air above so
|
|
139
|
+
a CTA never crowds the body (the live-update banner's reported cram). */
|
|
140
|
+
:scope [slot="content"] > footer {
|
|
141
|
+
display: flex;
|
|
142
|
+
gap: var(--a-space-2);
|
|
143
|
+
justify-content: flex-end;
|
|
144
|
+
margin-top: var(--alert-footer-gap, var(--a-space-1));
|
|
145
|
+
}
|
|
146
|
+
|
|
108
147
|
/* Trailing action area — optional single button or small button group.
|
|
109
148
|
flex-shrink:0 keeps it from collapsing; align-self:start anchors it
|
|
110
149
|
to the first text line under the `align-items:start` root.
|
|
@@ -140,10 +140,14 @@ slots:
|
|
|
140
140
|
content:
|
|
141
141
|
description: >-
|
|
142
142
|
Alert body. For single-line text use the `text=` attribute (alert.js
|
|
143
|
-
stamps a `<span slot="content">` automatically). For
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
stamps a `<span slot="content">` automatically). For structured
|
|
144
|
+
banners use card-ui's section rhythm INSIDE the content element
|
|
145
|
+
(gh#507): semantic `<header>` (title), `<section>` (body), and
|
|
146
|
+
`<footer>` (actions — right-aligned with its own step of air)
|
|
147
|
+
children of the slotted wrapper; the component owns the gaps
|
|
148
|
+
(`--alert-section-gap`, `--alert-footer-gap`), so spacing balances
|
|
149
|
+
without per-banner col-ui/row-ui improvisation. Free-form content
|
|
150
|
+
without those children lays out exactly as before.
|
|
147
151
|
leading:
|
|
148
152
|
description: >-
|
|
149
153
|
Leading icon. Stamped automatically from the `icon=` attribute;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { defineIfFree } from '../../core/register.js';
|
|
1
2
|
import { UIElement } from '../../core/element.js';
|
|
2
3
|
// NOTE: the A2UI renderer (<a2ui-root>) lives in @adia-ai/web-modules and is
|
|
3
4
|
// loaded lazily + guarded inside #ensureRenderer() (kicked off from connected()).
|
|
@@ -243,4 +244,6 @@ export class UICanvas extends UIElement {
|
|
|
243
244
|
}
|
|
244
245
|
}
|
|
245
246
|
|
|
246
|
-
|
|
247
|
+
// defineIfFree (gh#534): the prod bundle + module graph load in parallel;
|
|
248
|
+
// second registration must no-op, not throw.
|
|
249
|
+
defineIfFree('canvas-ui', UICanvas);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { defineIfFree } from '../../core/register.js';
|
|
1
2
|
import { UIElement } from '../../core/element.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -272,6 +273,8 @@ class UIChatInput extends UIElement {
|
|
|
272
273
|
this.#fileInput = null;
|
|
273
274
|
}
|
|
274
275
|
}
|
|
275
|
-
|
|
276
|
+
// defineIfFree (gh#534): the prod bundle + module graph load in parallel;
|
|
277
|
+
// second registration must no-op, not throw.
|
|
278
|
+
defineIfFree('chat-input-ui', UIChatInput);
|
|
276
279
|
|
|
277
280
|
export { UIChatInput };
|
package/components/code/code.css
CHANGED
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
--code-bg: var(--md-sys-color-neutral-background);
|
|
14
14
|
--code-fg: var(--md-sys-color-neutral-on-surface);
|
|
15
15
|
--code-border: var(--md-sys-color-neutral-outline-variant);
|
|
16
|
-
--code-header-bg: var(--
|
|
17
|
-
--code-header-fg: var(--
|
|
18
|
-
--code-copy-hover-bg: var(--
|
|
16
|
+
--code-header-bg: var(--md-sys-color-neutral-scrim-weakest);
|
|
17
|
+
--code-header-fg: var(--md-sys-color-neutral-on-surface-variant);
|
|
18
|
+
--code-copy-hover-bg: var(--md-sys-color-neutral-container-low);
|
|
19
19
|
--code-copy-hover-fg: var(--md-sys-color-neutral-on-surface);
|
|
20
20
|
|
|
21
21
|
/* ── Typography ── */
|
|
@@ -31,47 +31,50 @@
|
|
|
31
31
|
Active only when `[language]` triggers the CM mount. Still safe
|
|
32
32
|
to emit in read-only mode; unused until `.cm-editor` is in the
|
|
33
33
|
DOM. See docs/specs/code-editor.md §6. */
|
|
34
|
-
--code-gutter-bg: var(--
|
|
35
|
-
--code-gutter-fg: var(--
|
|
34
|
+
--code-gutter-bg: var(--md-sys-color-neutral-surface);
|
|
35
|
+
--code-gutter-fg: var(--md-sys-color-neutral-on-surface-variant);
|
|
36
36
|
/* Transparency-mixing in oklab — Safari < 18 has an OKLCH bug where
|
|
37
37
|
the transparent operand's hue resolves to 0, red-shifting the mix.
|
|
38
38
|
oklab is hue-agnostic and visually identical in fixed engines. */
|
|
39
39
|
--code-active-line-bg: color-mix(in oklab, var(--md-sys-color-primary-container) 40%, transparent);
|
|
40
40
|
--code-selection-bg: color-mix(in oklab, var(--md-sys-color-primary-container) 60%, transparent);
|
|
41
41
|
--code-selection-match: color-mix(in oklab, var(--md-sys-color-primary-container) 30%, transparent);
|
|
42
|
-
--code-cursor: var(--
|
|
42
|
+
--code-cursor: var(--md-sys-color-primary-active);
|
|
43
43
|
--code-focus-ring: var(--a-focus-ring);
|
|
44
44
|
|
|
45
45
|
/* ── Syntax highlight tokens ──
|
|
46
46
|
Map Lezer/CodeMirror highlight tag names to AdiaUI semantic
|
|
47
|
-
tokens
|
|
47
|
+
tokens — mapped DIRECTLY to --md-sys-color-* roles (operator ask
|
|
48
|
+
2026-07-30; the --a-* alias hop removed). tok-function uses
|
|
49
|
+
tertiary-active: brand has no md-sys mirror, and tertiary is the
|
|
50
|
+
identity-adjacent md-sys family. Overridable per-instance by setting `--code-tok-*` on
|
|
48
51
|
any ancestor. See docs/specs/code-editor.md §6.3 for the tag →
|
|
49
52
|
class → role map. */
|
|
50
53
|
--code-tok-comment: var(--md-sys-color-neutral-on-surface-variant);
|
|
51
|
-
--code-tok-keyword: var(--
|
|
52
|
-
--code-tok-string: var(--
|
|
53
|
-
--code-tok-number: var(--
|
|
54
|
-
--code-tok-boolean: var(--
|
|
54
|
+
--code-tok-keyword: var(--md-sys-color-primary-active);
|
|
55
|
+
--code-tok-string: var(--md-sys-color-success-active);
|
|
56
|
+
--code-tok-number: var(--md-sys-color-info-active);
|
|
57
|
+
--code-tok-boolean: var(--md-sys-color-info-active);
|
|
55
58
|
--code-tok-operator: var(--md-sys-color-neutral-on-surface);
|
|
56
|
-
--code-tok-punctuation: var(--
|
|
57
|
-
--code-tok-function: var(--
|
|
59
|
+
--code-tok-punctuation: var(--md-sys-color-neutral-on-surface-variant);
|
|
60
|
+
--code-tok-function: var(--md-sys-color-tertiary-active);
|
|
58
61
|
--code-tok-variable: var(--md-sys-color-neutral-on-surface);
|
|
59
|
-
--code-tok-type: var(--
|
|
62
|
+
--code-tok-type: var(--md-sys-color-warning-active);
|
|
60
63
|
--code-tok-property: var(--md-sys-color-neutral-on-surface);
|
|
61
|
-
--code-tok-tag: var(--
|
|
62
|
-
--code-tok-attribute: var(--
|
|
63
|
-
--code-tok-url: var(--
|
|
64
|
-
--code-tok-invalid: var(--
|
|
64
|
+
--code-tok-tag: var(--md-sys-color-primary-active);
|
|
65
|
+
--code-tok-attribute: var(--md-sys-color-warning-active);
|
|
66
|
+
--code-tok-url: var(--md-sys-color-info-active);
|
|
67
|
+
--code-tok-invalid: var(--md-sys-color-danger-active);
|
|
65
68
|
|
|
66
69
|
/* ── Lint markers (Phase 3 — editable JSON) ──
|
|
67
70
|
`@codemirror/lint` paints gutter markers + diagnostic tooltips
|
|
68
71
|
+ inline underlines. Only fires in editable mode with a linter
|
|
69
72
|
attached; read-only instances never see these selectors. */
|
|
70
|
-
--code-lint-gutter-bg: var(--
|
|
71
|
-
--code-lint-error: var(--
|
|
72
|
-
--code-lint-warning: var(--
|
|
73
|
-
--code-lint-info: var(--
|
|
74
|
-
--code-lint-tooltip-bg: var(--
|
|
73
|
+
--code-lint-gutter-bg: var(--md-sys-color-neutral-surface);
|
|
74
|
+
--code-lint-error: var(--md-sys-color-danger-active);
|
|
75
|
+
--code-lint-warning: var(--md-sys-color-warning-active);
|
|
76
|
+
--code-lint-info: var(--md-sys-color-info-active);
|
|
77
|
+
--code-lint-tooltip-bg: var(--md-sys-color-neutral-surface-high); /* §230-bundle (v0.5.9): elevated panel surface. Was orphaned --a-surface-floating. */
|
|
75
78
|
--code-lint-tooltip-fg: var(--md-sys-color-neutral-on-surface);
|
|
76
79
|
--code-lint-tooltip-border: var(--md-sys-color-neutral-outline-variant);
|
|
77
80
|
}
|
|
@@ -268,13 +271,13 @@
|
|
|
268
271
|
pointer-events: none;
|
|
269
272
|
}
|
|
270
273
|
:scope[readonly] .cm-editor {
|
|
271
|
-
background: var(--
|
|
274
|
+
background: var(--md-sys-color-neutral-surface);
|
|
272
275
|
}
|
|
273
276
|
:scope[aria-invalid="true"] {
|
|
274
|
-
border-color: var(--
|
|
277
|
+
border-color: var(--md-sys-color-danger-active);
|
|
275
278
|
}
|
|
276
279
|
:scope[aria-invalid="true"] .cm-focused {
|
|
277
|
-
outline: 2px solid var(--
|
|
280
|
+
outline: 2px solid var(--md-sys-color-danger-active);
|
|
278
281
|
outline-offset: -1px;
|
|
279
282
|
}
|
|
280
283
|
|
|
@@ -54,6 +54,15 @@
|
|
|
54
54
|
margin-bottom: var(--description-list-gap-row);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/* Responsive collapse (operator ruling 2026-07-30, the wizard-drawer
|
|
58
|
+
review step's settings layout): the two-column property|value grid
|
|
59
|
+
stacks on narrow viewports rather than squeezing the value column. */
|
|
60
|
+
@media (max-width: 480px) {
|
|
61
|
+
:scope[layout="inline"] {
|
|
62
|
+
grid-template-columns: 1fr;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
57
66
|
/* Inline: term and desc on one row */
|
|
58
67
|
:scope[layout="inline"] {
|
|
59
68
|
grid-template-columns: minmax(var(--description-list-term-min-width), max-content) 1fr;
|
|
@@ -286,6 +286,22 @@ drawer-ui [slot="panel"] > [slot="header"] > :is([slot="action"], [slot="close"]
|
|
|
286
286
|
gap: var(--drawer-header-gap);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
/* ═══════ Sticky progress block (operator ruling 2026-07-30) ═══════
|
|
290
|
+
A stepper-ui LEADING a drawer body is wizard chrome: it pins just below
|
|
291
|
+
the sticky header while the step panels scroll beneath — padded, on the
|
|
292
|
+
panel's own background so content can't ghost through, bled to the body
|
|
293
|
+
edges so the background spans full width. --drawer-sticky-offset
|
|
294
|
+
defaults to a one-line header's height (2×header-pad + one line +
|
|
295
|
+
divider); override for taller headers. */
|
|
296
|
+
drawer-ui [slot="panel"] > [slot="body"] > stepper-ui:first-child {
|
|
297
|
+
position: sticky;
|
|
298
|
+
top: var(--drawer-sticky-offset, calc(2 * var(--drawer-header-pad) + 1lh + 1px));
|
|
299
|
+
z-index: 1;
|
|
300
|
+
background: var(--drawer-bg);
|
|
301
|
+
margin: calc(-1 * var(--drawer-inset)) calc(-1 * var(--drawer-inset)) 0;
|
|
302
|
+
padding: var(--a-space-3) var(--drawer-inset);
|
|
303
|
+
}
|
|
304
|
+
|
|
289
305
|
/* ═══════ Body (section) ═══════
|
|
290
306
|
Padded by default. Multiple <section> siblings are allowed — they stack
|
|
291
307
|
inside the panel's own scroll region (see panel's overflow-y + sticky
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
/* ── Tokens ── */
|
|
4
4
|
--field-gap: var(--a-space-2);
|
|
5
5
|
--field-label-color: var(--md-sys-color-neutral-on-surface);
|
|
6
|
-
--
|
|
6
|
+
/* --a-ui-md, not -sm (operator ruling 2026-07-30): 13px base register /
|
|
7
|
+
14px in larger registers — 12px labels read too small beside 13-14px
|
|
8
|
+
control text. */
|
|
9
|
+
--field-label-size: var(--a-ui-md);
|
|
7
10
|
--field-label-weight: var(--a-weight-medium);
|
|
8
11
|
--field-required-color: var(--a-danger-strong);
|
|
9
12
|
--field-trailing-color: var(--md-sys-color-neutral-on-surface-variant);
|
package/components/list/list.css
CHANGED
|
@@ -118,7 +118,10 @@
|
|
|
118
118
|
box-sizing: border-box;
|
|
119
119
|
display: grid;
|
|
120
120
|
grid-template-columns: auto 1fr;
|
|
121
|
-
column-gap:
|
|
121
|
+
/* NO column-gap (gh#524): an iconless item's empty auto track still
|
|
122
|
+
charges the gap, indenting content behind a ghost cell. The
|
|
123
|
+
icon-to-text spacing rides the icon's own margin-inline-end
|
|
124
|
+
instead, so a zero-width track costs zero. */
|
|
122
125
|
row-gap: var(--list-item-gap-row);
|
|
123
126
|
font-size: var(--list-item-font-size);
|
|
124
127
|
color: var(--list-item-text-color);
|
|
@@ -141,6 +144,12 @@
|
|
|
141
144
|
grid-row: 1;
|
|
142
145
|
align-self: center;
|
|
143
146
|
color: var(--list-item-icon-color);
|
|
147
|
+
/* carries the old column-gap (gh#524) */
|
|
148
|
+
margin-inline-end: var(--list-item-gap-column);
|
|
149
|
+
}
|
|
150
|
+
/* An empty stamped icon span must not resurrect the ghost track. */
|
|
151
|
+
:scope [slot="icon"]:empty {
|
|
152
|
+
display: none;
|
|
144
153
|
}
|
|
145
154
|
|
|
146
155
|
:scope [slot="text"] {
|
|
@@ -177,6 +186,8 @@
|
|
|
177
186
|
grid-template-columns: auto 1fr auto;
|
|
178
187
|
}
|
|
179
188
|
:scope [slot="action"] {
|
|
189
|
+
/* carries the old column-gap on the trailing side (gh#524) */
|
|
190
|
+
margin-inline-start: var(--list-item-gap-column);
|
|
180
191
|
grid-column: 3;
|
|
181
192
|
grid-row: 1;
|
|
182
193
|
align-self: center;
|
|
@@ -48,6 +48,14 @@ export class UINavGroup extends UIElement {
|
|
|
48
48
|
#popover = null;
|
|
49
49
|
#anchorCleanup = null;
|
|
50
50
|
#headerEl = null;
|
|
51
|
+
// gh#501 — the gh#459 ruling ("the group CONTAINING the selected route
|
|
52
|
+
// fills") self-enforces: watch descendant nav-item [selected] flips and
|
|
53
|
+
// membership changes so the header glyph fills without consumer wiring.
|
|
54
|
+
// Targets ONLY the weight sync — a full render() from the observer loops:
|
|
55
|
+
// render's textContent writes are themselves subtree childList mutations.
|
|
56
|
+
// Stable ref for symmetric disconnect.
|
|
57
|
+
#onChildSelection = () => this.#syncHeaderWeight();
|
|
58
|
+
#selectionObserver = null;
|
|
51
59
|
|
|
52
60
|
#onHeaderKey = (e) => {
|
|
53
61
|
if (!this.collapsible) return;
|
|
@@ -80,6 +88,21 @@ export class UINavGroup extends UIElement {
|
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
this.#headerEl?.addEventListener('keydown', this.#onHeaderKey);
|
|
91
|
+
|
|
92
|
+
// gh#501 — fill-on-child-selection needs no consumer wiring: observe
|
|
93
|
+
// [selected] flips on descendants + child list churn. Watching the
|
|
94
|
+
// whole subtree includes this host's own [selected], which render()
|
|
95
|
+
// reads anyway; render() writes only the icon's [weight], which the
|
|
96
|
+
// attributeFilter excludes, so the observer can't feed back.
|
|
97
|
+
if (!this.#selectionObserver) {
|
|
98
|
+
this.#selectionObserver = new MutationObserver(this.#onChildSelection);
|
|
99
|
+
this.#selectionObserver.observe(this, {
|
|
100
|
+
subtree: true,
|
|
101
|
+
childList: true,
|
|
102
|
+
attributes: true,
|
|
103
|
+
attributeFilter: ['selected'],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
83
106
|
}
|
|
84
107
|
|
|
85
108
|
render() {
|
|
@@ -99,9 +122,27 @@ export class UINavGroup extends UIElement {
|
|
|
99
122
|
// path; [open] keeps driving aria-expanded only. A state-driven weight
|
|
100
123
|
// swap, not a CSS color change, since Phosphor ships filled/regular as
|
|
101
124
|
// distinct SVGs.
|
|
125
|
+
this.#syncHeaderWeight();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Own [selected] OR any selected descendant item (gh#501) — the ruling's
|
|
129
|
+
// "group CONTAINING the selected route", self-enforcing. Skips the write
|
|
130
|
+
// when the weight is already right so the observer path stays quiet.
|
|
131
|
+
#syncHeaderWeight() {
|
|
132
|
+
const containsSelection =
|
|
133
|
+
this.hasAttribute('selected') || !!this.querySelector('nav-item-ui[selected]');
|
|
134
|
+
// Reflect contains-selection for CSS (gh#522): the icon COLOR half of
|
|
135
|
+
// the selection language keys on this host attribute — weight alone
|
|
136
|
+
// read as an unselected white glyph beside nav-item's primary one.
|
|
137
|
+
// The observer's attributeFilter is ['selected'], so this write on
|
|
138
|
+
// the host cannot feed back.
|
|
139
|
+
if (containsSelection !== this.hasAttribute('data-selected-within')) {
|
|
140
|
+
this.toggleAttribute('data-selected-within', containsSelection);
|
|
141
|
+
}
|
|
102
142
|
const iconEl = this.querySelector('[slot="header"] [slot="icon"] icon-ui');
|
|
103
|
-
if (iconEl)
|
|
104
|
-
|
|
143
|
+
if (!iconEl) return;
|
|
144
|
+
const weight = containsSelection ? 'fill' : 'regular';
|
|
145
|
+
if (iconEl.getAttribute('weight') !== weight) iconEl.setAttribute('weight', weight);
|
|
105
146
|
}
|
|
106
147
|
|
|
107
148
|
showPopover() {
|
|
@@ -165,5 +206,7 @@ export class UINavGroup extends UIElement {
|
|
|
165
206
|
this.#anchorCleanup?.();
|
|
166
207
|
this.#anchorCleanup = null;
|
|
167
208
|
this.#popover?.hidePopover?.();
|
|
209
|
+
this.#selectionObserver?.disconnect();
|
|
210
|
+
this.#selectionObserver = null;
|
|
168
211
|
}
|
|
169
212
|
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
--nav-group-fg-hover: var(--a-fg-strong);
|
|
15
15
|
--nav-group-fg-muted: var(--a-fg-muted);
|
|
16
16
|
--nav-group-fg-selected: var(--a-fg-strong);
|
|
17
|
+
--nav-group-icon-fg-selected: var(--md-sys-color-primary); /* one selection color with --nav-item-accent (gh#522) */
|
|
17
18
|
--nav-group-bg-hover: var(--a-bg-muted);
|
|
18
19
|
--nav-group-icon-size: calc(var(--nav-group-row-height) - var(--a-space-2));
|
|
19
20
|
--nav-group-badge-size: var(--a-ui-sm);
|
|
@@ -52,10 +53,18 @@
|
|
|
52
53
|
/* Selected-look header treatment keys on [selected] — the CSS half of
|
|
53
54
|
gh issue 459 (PR 460 corrected the icon weight): the group CONTAINING
|
|
54
55
|
the selected route reads strong; a merely-expanded group does not. */
|
|
55
|
-
:scope[selected] > [slot="header"]
|
|
56
|
-
:scope[selected] > [slot="header"] [slot="icon"] {
|
|
56
|
+
:scope[selected] > [slot="header"] {
|
|
57
57
|
color: var(--nav-group-fg-selected);
|
|
58
58
|
}
|
|
59
|
+
/* Icon color = the SELECTION color, one language with nav-item's accent
|
|
60
|
+
glyph (gh#522, operator ruling 2026-07-30): filled + primary whenever
|
|
61
|
+
this group is selected OR contains the selected route.
|
|
62
|
+
[data-selected-within] is reflected by #syncHeaderWeight (gh#501) so
|
|
63
|
+
the JS-detected contains-selection state is CSS-addressable. */
|
|
64
|
+
:scope[selected] > [slot="header"] [slot="icon"],
|
|
65
|
+
:scope[data-selected-within] > [slot="header"] [slot="icon"] {
|
|
66
|
+
color: var(--nav-group-icon-fg-selected);
|
|
67
|
+
}
|
|
59
68
|
|
|
60
69
|
/* Header row */
|
|
61
70
|
[slot="header"] {
|
|
@@ -91,8 +91,16 @@ export class UIProgressRow extends UIElement {
|
|
|
91
91
|
this.#labelEl.textContent = this.label;
|
|
92
92
|
this.#labelEl.hidden = !this.label;
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
// The [meta] ATTR owns the text when set. When it's absent, authored
|
|
95
|
+
// [slot="meta"] content — e.g. meta text with a trailing delta badge
|
|
96
|
+
// (gh#502) — is left intact instead of being wiped + hidden; only a
|
|
97
|
+
// genuinely empty meta element hides.
|
|
98
|
+
if (this.meta) {
|
|
99
|
+
this.#metaEl.textContent = this.meta;
|
|
100
|
+
this.#metaEl.hidden = false;
|
|
101
|
+
} else {
|
|
102
|
+
this.#metaEl.hidden = !this.#metaEl.hasChildNodes();
|
|
103
|
+
}
|
|
96
104
|
|
|
97
105
|
if (this.value != null && this.value >= 0) {
|
|
98
106
|
this.#progressEl.setAttribute('value', String(this.value));
|
|
@@ -96,6 +96,13 @@
|
|
|
96
96
|
width: 100%;
|
|
97
97
|
max-width: var(--richtext-max-width);
|
|
98
98
|
padding: var(--richtext-py) var(--richtext-px);
|
|
99
|
+
/* Body spec set ONCE at the container (gh#546): p was pinned to
|
|
100
|
+
--richtext-body-size while li/ul had no font rule and inherited the
|
|
101
|
+
HOST page's larger base — chat-rendered lists read bigger than the
|
|
102
|
+
paragraph beside them. Everything now inherits this; headings/code
|
|
103
|
+
still override explicitly. */
|
|
104
|
+
font-size: var(--richtext-body-size);
|
|
105
|
+
line-height: var(--richtext-body-leading);
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
/* [flush] — paragraph-grade embedding (yaml `flush` prop): drop the
|
|
@@ -106,6 +106,11 @@
|
|
|
106
106
|
"type": "string",
|
|
107
107
|
"default": ""
|
|
108
108
|
},
|
|
109
|
+
"no-radio": {
|
|
110
|
+
"description": "Suppress the single-select radio indicator on option rows (gh#498). For menu-shaped switchers — workspace or user identity menus — where the trigger already shows the committed value and a per-row radio reads as redundant selection language. Rows keep their layout and aria-selected state; the trigger and selected-row weight carry the signal. No effect under [multiple]. IMPLIED by [mark] — a mark declares an identity switcher, which is always menu-shaped (gh#498 reopen: per-instance opt-outs proved forgettable).",
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"default": false
|
|
113
|
+
},
|
|
109
114
|
"open": {
|
|
110
115
|
"description": "Whether the listbox is open",
|
|
111
116
|
"type": "boolean",
|