@adia-ai/web-components 0.7.23 → 0.7.25
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 +56 -25
- package/README.md +2 -2
- package/USAGE.md +60 -15
- package/components/accordion/accordion-item.a2ui.json +30 -1
- package/components/accordion/accordion-item.yaml +33 -0
- package/components/accordion/accordion.a2ui.json +9 -0
- package/components/accordion/accordion.class.js +53 -3
- package/components/accordion/accordion.css +61 -3
- package/components/accordion/accordion.d.ts +12 -0
- package/components/accordion/accordion.yaml +17 -0
- package/components/code/code.class.js +1 -1
- package/components/display-field/display-field.a2ui.json +185 -0
- package/components/display-field/display-field.css +91 -0
- package/components/display-field/display-field.d.ts +26 -0
- package/components/display-field/display-field.examples.md +44 -0
- package/components/display-field/display-field.js +141 -0
- package/components/display-field/display-field.test.js +115 -0
- package/components/display-field/display-field.yaml +191 -0
- package/components/drawer/drawer.class.js +2 -2
- package/components/feed/feed.a2ui.json +1 -1
- package/components/feed/feed.class.js +1 -1
- package/components/feed/feed.d.ts +1 -1
- package/components/feed/feed.yaml +2 -2
- package/components/field/field.class.js +1 -1
- package/components/icon/icon.class.js +34 -1
- package/components/index.js +1 -0
- package/components/loading-overlay/loading-overlay.class.js +1 -1
- package/components/loading-overlay/loading-overlay.yaml +1 -1
- package/components/modal/modal.class.js +1 -1
- package/components/nav/nav.class.js +1 -1
- package/components/nav/nav.examples.md +4 -4
- package/components/popover/popover.class.js +1 -1
- package/components/spinner/spinner.class.js +1 -1
- package/components/spinner/spinner.yaml +1 -1
- package/components/table/table.class.js +42 -11
- package/components/table/table.test.js +53 -0
- package/components/toast/toast.class.js +1 -1
- package/core/icons.js +14 -0
- package/custom-elements.json +5723 -2865
- package/dist/theme-provider.min.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +87 -79
- package/dist/web-components.sheet.js +1 -1
- package/package.json +3 -2
- package/styles/components.css +1 -0
- package/traits/CATEGORIES.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
2
|
|
|
3
|
+
## [0.7.25] — 2026-07-03
|
|
4
|
+
|
|
5
|
+
Upstream consumer finding from `adia-pay` (F10, sibling of F1–F9 shipped in 0.7.24) — a token-modeled `variant="flat|contained"` posture for the accordion, plus its two footnote bugs.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **`accordion-ui` / `accordion-item-ui` (`components/accordion/`) — `variant="flat|contained"` posture.** New reflected `variant` attribute on both the host and each item (default `flat`, pixel-unchanged from today — verified via the new `accordion-contained-probe.mjs`). `variant="contained"` on the host gives every child item a bounded surface — background, border, and radius spanning its header + open body, with a divider between them once expanded — the composition for embedding an accordion inside `<card-ui>`; a single item can opt out with its own `variant="flat"` (or opt IN against a flat host with `variant="contained"`). Four new item tokens carry the posture and are consumer-overridable in **both** postures: `--accordion-item-bg`, `--accordion-item-border` (full shorthand, mirrors `--card-border`), `--accordion-item-divider`, `--accordion-item-body-pt` — all default to the flat, invisible value. Contained is a token-only re-point plus three documented layout exceptions (`overflow:hidden` clip, `border-radius:0` on the header pill, and focus-ring relocation from the header onto the item surface) — added to `component-token-contract.md`'s sanctioned mode-attribute table alongside `progress-ui`/`pagination-ui`. Nested accordions stay isolated: a flat accordion inside a contained item's body is unaffected by the host's posture (direct-child `>` combinator, not a descendant selector). New examples: standalone contained, contained inside `card-ui`, and a per-item flat override. (upstream finding F10, ticket AC-1…AC-3/AC-5)
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **`accordion-item-ui` — the disclosure caret now survives a custom `[slot="header"]`.** Authoring your own header (icon + title + action buttons) previously suppressed the caret entirely — the component only ever stamped one alongside a header it ALSO stamped. `connected()` now stamps a `caret-down` `icon-ui` into any authored header that doesn't already contain a `[slot="caret"]`, scoped to the header element specifically (a caret placed in `[slot="body"]` no longer falsely suppresses it). Author your own `[slot="caret"]` (even empty) to opt out — no new attribute; documented on the `caret` slot in `accordion-item.yaml`. (upstream finding F10 footnote FN-1)
|
|
12
|
+
- **`accordion-item-ui` — `[text]` no longer clobbers an authored `[slot="header-text"]`.** The auto-stamped label is now marked with a `data-autolabel` DOM attribute (survives disconnect→reconnect), and `render()` only drives that marked label — a hand-authored `[slot="header-text"]` inside a custom header is never overwritten. Setting `text` alongside an authored header-text label is now a silent no-op by design (was a silent clobber before). (upstream finding F10 footnote FN-2)
|
|
13
|
+
- **`accordion-item-ui` — the default (auto-stamped) header is now keyboard-operable.** It was mouse-only: no `tabindex`, no keydown handling. The auto-stamped header now carries `tabindex="0"`, `role="button"`, and `aria-expanded` (kept in sync on every toggle); `Enter` and `Space` both toggle it, routed through the existing click handler (`header.click()`) so there is exactly one toggle code path. A consumer-authored header (e.g. `<button slot="header">`) already worked and is unaffected — this closes a pre-existing gap for the default header only, folded into this arc on operator review (an additive a11y improvement, not a regression).
|
|
14
|
+
|
|
15
|
+
### Maintenance
|
|
16
|
+
- **`dist/` bundles regenerated** (`web-components.min.{css,js}`, `web-components.sheet.js`, `theme-provider.min.js`) to carry the accordion changes above.
|
|
17
|
+
- **Doc-comment path references corrected** (`docs/specs/...` → `.claude/docs/specs/...`) across `patterns/` (2 `.examples.html` + 1 README) and `traits/` (`CATEGORIES.md` + 1 `.examples.html`) — propagated from the repo-wide `docs/` → `.claude/docs/` migration (2026-07-01) on the first full `components.mjs` regen since; no functional change, `styles/type-scale-review.examples.html` likewise.
|
|
18
|
+
|
|
19
|
+
## [0.7.24] — 2026-07-01
|
|
20
|
+
|
|
21
|
+
Upstream consumer findings from `adia-pay` against installed `0.7.23` (F1–F6).
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- **`display-field-ui` (`components/display-field/`) — new display-only labeled-value primitive.** Fills a capability gap: a field-shaped read-out for a static or masked value (a card on file, `•••• 4242`, an account id) or a labeled slot that hosts a third-party element (a Stripe Element iframe) under a proper caption. Unlike `field-ui` it wraps **no** interactive control — no focus, no contenteditable, no form participation, no `[for]`/id-minting — so a readonly `input-ui` (which keeps input semantics) is no longer the only option. Props: `label` (required; names the group via `role="group"` + `aria-labelledby`), `value` (static text), `variant` (`default` | `masked` — mono/tabular treatment so `•••• 4242` aligns), `hint` (caption + `aria-describedby`), `icon` (leading glyph). The value comes from the `value` attr **or** an unnamed default-slot child (the foreign-element path) — slot content wins when both are present. Ships yaml + css + js + d.ts + a2ui sidecar + demo (`display-field.examples.html`) + 6 unit tests; registered in the component barrel + `styles/components.css`; `dist/` + `custom-elements.json` (120 → 121 modules) regenerated. Additive (PATCH). (upstream finding F5)
|
|
25
|
+
- **`table-ui` (`components/table/`) — `rowExpandable` per-row expand gate.** `expandable` was host-level: every row got the same `caret-right` toggle and one host-level `expandRenderer` drove all detail panes, so heterogeneous rows (a *succeeded* payment needing no detail vs. a *failed* one that expands to a reason) could not vary the affordance. New optional `rowExpandable(row, index) => boolean` callback gates the caret per row — non-expandable rows keep the reserved expand-column cell (grid alignment never shifts) but show no caret and can't open a detail pane; `toggleExpand()` is guarded to match (it still collapses an already-open row if the predicate later flips, so a row can't get stuck open). `null` (default) preserves the legacy "every row expandable" behavior. Demo: the `rowExpandable` section in `table.examples.html` (only Failed payments expand). Regression: 3 tests in `table.test.js`. Additive — no API removed (PATCH). (upstream finding F6)
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- **`icon-ui` (`components/icon/`) — fails loud when the icon registry was never wired.** Under Vite 8 / rolldown the zero-config `import.meta.glob('/node_modules/@phosphor-icons/…')` path in `icons-phosphor.js` does not transform from inside a published dependency, leaving the registry empty so every `<icon-ui>` renders blank — previously **silently** (a single missing icon warned, but a wholly-unwired registry did not). New `iconRegistryUnwired()` predicate (`core/icons.js`) distinguishes "never wired" (`registry.size === 0 && !registryReady`) from "one bad name"; `icon.class.js` schedules a one-shot, macrotask-deferred `console.error` naming the exact fix (install `@phosphor-icons/core` + call `installIconLoaders` from the app entry) only when a named icon resolves to nothing AND the registry is unwired. The deferral means a correctly-wired app entry is never false-flagged. Documented as the primary bundler path in `USAGE.md` § Icons. (upstream finding F1)
|
|
29
|
+
- **`custom-elements.json` — manifest no longer fabricates nonexistent modules.** `scripts/build/generate-custom-elements-json.mjs` emitted a `javascript-module` + class + `custom-element-definition` for every component yaml by assuming a `components/<dir>/<base>.js` file existed — fabricating e.g. `UIHeader` → `header.js` (the CSS-only `header-ui` has no class file) and pointing co-located children (menu-item-ui, menu-divider-ui, …) at nonexistent per-child `.js` files. The generator now scans the actual `.js` sources for `customElements.define` / `defineIfFree` / `defineIfUndefined` calls, maps each tag to the file that really defines it, groups declarations by real module path, and lists genuinely CSS-only tags (aside/footer/header/section-ui) as skipped. Regenerated manifest: 120 modules / 134 tags, 0 dangling file paths (was 110 modules carrying fabricated paths). (upstream finding F4)
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- **`@phosphor-icons/core` is now a direct dependency (`^2.1.1`).** It was referenced by the icon-loader glob but absent from every dependency field, so the documented zero-config icon path could not resolve its SVG assets from a clean install. Added to `dependencies` so the assets resolve; the app still wires the loader glob from its own source graph (see `USAGE.md` § Icons / finding F1). (upstream finding F2)
|
|
33
|
+
|
|
3
34
|
## [0.7.23] — 2026-06-30
|
|
4
35
|
|
|
5
36
|
### Fixed
|
|
@@ -26,7 +57,7 @@
|
|
|
26
57
|
## [0.7.19] — 2026-06-10
|
|
27
58
|
|
|
28
59
|
### Fixed
|
|
29
|
-
- **`icon-ui` — glyphs always paint on the standalone import path.** Importing `components/icon` directly (or a demo page loading only `./icon.js`) never loaded `core/icons-phosphor.js`, so the weight-loader map stayed empty and every `getIcon()` returned `''` — **silently** (the not-ready guard suppressed the warning): blank icons, zero console errors. Two fixes: `icon.js` now imports the Phosphor loader as a side-effect (the barrel paths already did), and `icon.class.js` gains a signal-reactive retry (`#rev` bumped by `whenIconRegistryReady`, aborted symmetrically in `disconnected()`) so elements that connect *after* the loaders install — e.g. fetched-and-injected demo markup — re-render once the registry is ready. Production (barrel-served) was never affected; the docs/demo single-component path was. Regression probe: `scripts/dev/icon-paint-probe.mjs`. `dist/web-components.min.js` (and the web-modules kitchen-sink bundle) regenerated to carry the fix.
|
|
60
|
+
- **`icon-ui` — glyphs always paint on the standalone import path.** Importing `components/icon` directly (or a demo page loading only `./icon.js`) never loaded `core/icons-phosphor.js`, so the weight-loader map stayed empty and every `getIcon()` returned `''` — **silently** (the not-ready guard suppressed the warning): blank icons, zero console errors. Two fixes: `icon.js` now imports the Phosphor loader as a side-effect (the barrel paths already did), and `icon.class.js` gains a signal-reactive retry (`#rev` bumped by `whenIconRegistryReady`, aborted symmetrically in `disconnected()`) so elements that connect *after* the loaders install — e.g. fetched-and-injected demo markup — re-render once the registry is ready. Production (barrel-served) was never affected; the .claude/docs/demo single-component path was. Regression probe: `scripts/dev/icon-paint-probe.mjs`. `dist/web-components.min.js` (and the web-modules kitchen-sink bundle) regenerated to carry the fix.
|
|
30
61
|
|
|
31
62
|
## [0.7.18] — 2026-06-09
|
|
32
63
|
|
|
@@ -84,7 +115,7 @@
|
|
|
84
115
|
|
|
85
116
|
### Changed
|
|
86
117
|
|
|
87
|
-
- **BREAKING (pre-1.0 PATCH cadence) — the token-theme attribute `data-theme` is renamed `theme`.** `<html data-theme="ocean">` → `<html theme="ocean">`; `[data-theme="…"]` selectors → `[theme="…"]`; the token-root selector `:root, theme-ui, [data-theme]` → `:root, theme-ui, [theme], theme-provider` across the 14 foundation files (so `<theme-provider>` is itself a token-root). Cleaner, and it converges with `<canvas-ui theme="…">`, which already scoped AdiaUI themes the same way. Done as a repo-wide word-boundary sweep — compound attributes (`data-theme-slug`, `data-themes-grid`, `data-themed`, …) are preserved (the sweep also touched the styles/, traits/, and patterns/ trees). **Consumers using `data-theme="…"` must switch to `theme="…"`** — see
|
|
118
|
+
- **BREAKING (pre-1.0 PATCH cadence) — the token-theme attribute `data-theme` is renamed `theme`.** `<html data-theme="ocean">` → `<html theme="ocean">`; `[data-theme="…"]` selectors → `[theme="…"]`; the token-root selector `:root, theme-ui, [data-theme]` → `:root, theme-ui, [theme], theme-provider` across the 14 foundation files (so `<theme-provider>` is itself a token-root). Cleaner, and it converges with `<canvas-ui theme="…">`, which already scoped AdiaUI themes the same way. Done as a repo-wide word-boundary sweep — compound attributes (`data-theme-slug`, `data-themes-grid`, `data-themed`, …) are preserved (the sweep also touched the styles/, traits/, and patterns/ trees). **Consumers using `data-theme="…"` must switch to `theme="…"`** — see `.claude/docs/MIGRATION GUIDE.md`.
|
|
88
119
|
- **CDN bundles rebuilt** — `dist/web-components.min.{css,js}` + `dist/host.min.css` regenerated so the `[theme]` rename, `<theme-provider>` registration, and the new register twins reach `@adia-ai/web-components@0.7` CDN consumers.
|
|
89
120
|
|
|
90
121
|
### Fixed
|
|
@@ -196,7 +227,7 @@
|
|
|
196
227
|
|
|
197
228
|
### Changed
|
|
198
229
|
|
|
199
|
-
- **Reverted the OD-5 `-default` token-shadowing layer — component CSS now declares a single un-suffixed token per property** — `var(--card-bg, var(--card-bg-default))` → `var(--card-bg)` across 119 component + module CSS files; variants/states re-point the un-suffixed `--<component>-*` token directly (`:where(:scope)` keeps the base at zero specificity). The 2026-05-24 OD-5 split (internal `--<c>-X-default` + public `--<c>-X` read through a fallback chain) added read-past noise without paying for itself: the one capability it bought — ancestor-surface inheritance of *component-named* tokens — had no real usage (a repo sweep found only on-element attribute hooks + parent→child composition, both of which win by specificity and survive). **Consumer overriding is unchanged** for the four real vectors (`--a-*` upstream · on-element `card-ui { --card-bg: … }` / inline · parent→child composition · `@layer overrides`); the *only* behavior change is that a `--<component>-*` token set on a non-targeting **ancestor** no longer inherits in (theme via `--a-*` or `@layer overrides`). No public component/prop API change. Inverse codemod `scripts/refactor/undo-od5-token-shadowing.mjs` (2-level + 3-level chain collapse, precise pair-derived strip, collision-safe residual rewire); forward `od5-token-shadowing.mjs` retired;
|
|
230
|
+
- **Reverted the OD-5 `-default` token-shadowing layer — component CSS now declares a single un-suffixed token per property** — `var(--card-bg, var(--card-bg-default))` → `var(--card-bg)` across 119 component + module CSS files; variants/states re-point the un-suffixed `--<component>-*` token directly (`:where(:scope)` keeps the base at zero specificity). The 2026-05-24 OD-5 split (internal `--<c>-X-default` + public `--<c>-X` read through a fallback chain) added read-past noise without paying for itself: the one capability it bought — ancestor-surface inheritance of *component-named* tokens — had no real usage (a repo sweep found only on-element attribute hooks + parent→child composition, both of which win by specificity and survive). **Consumer overriding is unchanged** for the four real vectors (`--a-*` upstream · on-element `card-ui { --card-bg: … }` / inline · parent→child composition · `@layer overrides`); the *only* behavior change is that a `--<component>-*` token set on a non-targeting **ancestor** no longer inherits in (theme via `--a-*` or `@layer overrides`). No public component/prop API change. Inverse codemod `scripts/refactor/undo-od5-token-shadowing.mjs` (2-level + 3-level chain collapse, precise pair-derived strip, collision-safe residual rewire); forward `od5-token-shadowing.mjs` retired; `.claude/docs/specs/component-token-contract.md` rewritten (§History). Internal: `modal`/`swiper` `getComputedStyle` reads + 5 CSS-string-match tests re-pointed to the un-suffixed names. Verified: suite 1526/1526, `components --verify` clean, bundles fresh, visual QA (composition intact).
|
|
200
231
|
- **Typographic registers re-scaled — regular (default) + prose (MINOR behavior change)** — the regular register's inset compressed `8/16/24 → 14/16/18` and its gap re-based to a clean `value × --a-gap-k` multiplier (`8/12/16 → 10/12/14`, replacing the `half+half·k` form); `md` (the default tier) is unchanged for both, so only `[size=sm]`/`[size=lg]` containers shift. Prose moved one rung up (inset → 32/40/48, gap → 16/20/24). **Radius is now a register-scaled axis** — each register sets its own `--a-radius-min/max` (verse ≤16px · regular 20px=base · prose ≤28px) feeding the existing `clamp(min, k·max·tier-k, max)` formula. All values verified by `scripts/qa/register-scale-probe.mjs` (9 cells × 5 axes).
|
|
201
232
|
- **Demo scaffolds migrated to the `--a-font-family` token** — the ~114 `patterns/` + `traits/` demo `.html` scaffolds (plus the per-component demos) swapped their hand-rolled `:where(html, body) { font-family: var(--a-font) }` boilerplate to `var(--a-font-family)`, tracking the font-family-floor token rename; `patterns/search-discovery` additionally dropped a stray inline `max-width` so the results card self-frames. Demo-layer migration only — no component or CSS-API change.
|
|
202
233
|
|
|
@@ -321,7 +352,7 @@
|
|
|
321
352
|
### Changed — global styles assigned to `@layer` cascade layers (ADR-0038)
|
|
322
353
|
|
|
323
354
|
- `packages/web-components/styles/` now assigns every rule to a named cascade layer — `@layer reset, tokens, elements, components, utilities, context, overrides` — so precedence is **declared once** instead of faked per-rule via specificity/`:where()`. The published bundle + barrel carry the layers; **rule content is unchanged** — only layer membership. Cuts: `resets.css` → `reset`; `colors/` + `foundation/` → `tokens`; `type/elements.css` → `elements`; the 128 scoped components → `components`; `api/{sizing,text,layout}` + `[variant]` → `utilities`; `themes.css` + `prose.css` → `context`; `overrides` declared topmost and **reserved (empty)** for consumer rules. A consumer rule in `@layer overrides` now wins by layer order with no `!important` and no specificity war (proven: a `(0,0,1)` `badge-ui{font-weight:321}` override beats both the component's `@scope` 500 and a `[weight="bold"]` 700).
|
|
324
|
-
- **One intentional behavior change (IPC-04).** Utility attributes — `[weight]` `[color]` `[transform]` `[text-align]` `[variant]` — now **override** a component's own `@scope` rule (they sit in `utilities`, above `components`). Previously they lost to component `@scope` by scope-proximity, and api/text.css documented that limitation — now retired. Measured blast radius: **39 component×property honorings across 128 components** (25 `color`, 10 `font-weight`, 3 `text-align`, 1 `text-transform`), zero breakage. Every *other* cut is behavior-neutral (real-browser computed-style probe 0 diffs; token identity byte-identical). The `ul/ol[role="list"]` reset and the `h1–h6` role defaults were relocated into `type/elements.css` (element-default refinements that must win by specificity *within* the `elements` layer). See ADR-0038 +
|
|
355
|
+
- **One intentional behavior change (IPC-04).** Utility attributes — `[weight]` `[color]` `[transform]` `[text-align]` `[variant]` — now **override** a component's own `@scope` rule (they sit in `utilities`, above `components`). Previously they lost to component `@scope` by scope-proximity, and api/text.css documented that limitation — now retired. Measured blast radius: **39 component×property honorings across 128 components** (25 `color`, 10 `font-weight`, 3 `text-align`, 1 `text-transform`), zero breakage. Every *other* cut is behavior-neutral (real-browser computed-style probe 0 diffs; token identity byte-identical). The `ul/ol[role="list"]` reset and the `h1–h6` role defaults were relocated into `type/elements.css` (element-default refinements that must win by specificity *within* the `elements` layer). See ADR-0038 + `.claude/docs/specs/cascade-layer-architecture.md`.
|
|
325
356
|
|
|
326
357
|
### Added — `<select-ui>` per-option `icon` / `avatar`, reflected in the trigger
|
|
327
358
|
|
|
@@ -329,7 +360,7 @@
|
|
|
329
360
|
|
|
330
361
|
### Changed — block-level display by default + universal `[inline]` attribute (ADR-0037)
|
|
331
362
|
|
|
332
|
-
- Composite / control / container primitives now default to a **block-level** host `display` (`flex`/`block`/`grid`); the new universal **`[inline]`** boolean opts back to inline-level (`inline-flex`/`inline-block`/`inline-grid`). Flipped 14 primitives: `button` (text → full-width block, icon-only held inline via `:not([text])`), `color-input`, `date-range-picker`, `datetime-picker`, `time-picker`, `breadcrumb`, `pagination`, `segmented`, `toggle-group`, `toggle-scheme`, `menu`, `popover`, `image`, `qr-code`. **Text-flow atoms stay inline** (`text` `link` `mark` `number-format` `relative-time` `inline-edit` `inline-message` `badge` `tag` `chip` `kbd` `icon` `radio` `check` `switch` `avatar` `swatch` `rating` `spinner`). CSS-only — per-component `:scope[inline]` (specificity 0,2,0 reliably overrides `:scope`); no yaml/JS/sidecar (universal-attribute precedent: `[grow]`/`[hidden]`). **Inside `row-ui`/`col-ui`/`grid-ui` the flip is a no-op** (flex/grid items are blockified), so real-composition rendering is unchanged — only standalone-in-block-flow goes full-width. `field`/`fields` carve out `[inline]` for their single-row *layout* mode. `api/layout.css` documents the per-component rationale. See ADR-0037 +
|
|
363
|
+
- Composite / control / container primitives now default to a **block-level** host `display` (`flex`/`block`/`grid`); the new universal **`[inline]`** boolean opts back to inline-level (`inline-flex`/`inline-block`/`inline-grid`). Flipped 14 primitives: `button` (text → full-width block, icon-only held inline via `:not([text])`), `color-input`, `date-range-picker`, `datetime-picker`, `time-picker`, `breadcrumb`, `pagination`, `segmented`, `toggle-group`, `toggle-scheme`, `menu`, `popover`, `image`, `qr-code`. **Text-flow atoms stay inline** (`text` `link` `mark` `number-format` `relative-time` `inline-edit` `inline-message` `badge` `tag` `chip` `kbd` `icon` `radio` `check` `switch` `avatar` `swatch` `rating` `spinner`). CSS-only — per-component `:scope[inline]` (specificity 0,2,0 reliably overrides `:scope`); no yaml/JS/sidecar (universal-attribute precedent: `[grow]`/`[hidden]`). **Inside `row-ui`/`col-ui`/`grid-ui` the flip is a no-op** (flex/grid items are blockified), so real-composition rendering is unchanged — only standalone-in-block-flow goes full-width. `field`/`fields` carve out `[inline]` for their single-row *layout* mode. `api/layout.css` documents the per-component rationale. See ADR-0037 + `.claude/docs/specs/attribute-api-system.md` §5.
|
|
333
364
|
|
|
334
365
|
### Changed — `chevron` → `caret` terminology sweep (FEEDBACK-90, ADR-0036 follow-up)
|
|
335
366
|
|
|
@@ -1103,11 +1134,11 @@ Three pre-v0.4.0 `patterns/*.examples.html` files used legacy markup retired by
|
|
|
1103
1134
|
## [0.6.15] — 2026-05-21
|
|
1104
1135
|
|
|
1105
1136
|
### Fixed
|
|
1106
|
-
- **`installIconLoaders` / `installIconLoadersForRegistered` no longer silently accept a malformed shape (FB-07).** The previous behavior was `weightModules = { ...EMPTY_WEIGHTS, ...modules }` which spread any top-level keys verbatim. A flat path→svg glob (the documented quick-start shape; see FB-09) had its `/path/foo.svg` keys spread at the top level of `weightModules`, leaving every per-weight slot empty. Every `<icon-ui>` then rendered the icon NAME as visible text in its slot — confusing to debug because the per-icon `warnMissingIcon` console message points at name-resolution issues (Phosphor alias, `registerIcon`, etc.), not at loader-shape issues. The fix shape-detects three cases: (1) per-weight map keyed by `regular`/`thin`/`light`/`bold`/`fill`/`duotone` installs verbatim; (2) flat path→svg map auto-promotes to `{ regular: <flat> }` with a one-time `console.warn` so the caller knows to wrap explicitly (and so bold/fill/etc. aren't silently lost); (3) anything else logs `console.error` with the received key sample and aborts the install (registry stays unchanged). Net: the documented flat shape from
|
|
1137
|
+
- **`installIconLoaders` / `installIconLoadersForRegistered` no longer silently accept a malformed shape (FB-07).** The previous behavior was `weightModules = { ...EMPTY_WEIGHTS, ...modules }` which spread any top-level keys verbatim. A flat path→svg glob (the documented quick-start shape; see FB-09) had its `/path/foo.svg` keys spread at the top level of `weightModules`, leaving every per-weight slot empty. Every `<icon-ui>` then rendered the icon NAME as visible text in its slot — confusing to debug because the per-icon `warnMissingIcon` console message points at name-resolution issues (Phosphor alias, `registerIcon`, etc.), not at loader-shape issues. The fix shape-detects three cases: (1) per-weight map keyed by `regular`/`thin`/`light`/`bold`/`fill`/`duotone` installs verbatim; (2) flat path→svg map auto-promotes to `{ regular: <flat> }` with a one-time `console.warn` so the caller knows to wrap explicitly (and so bold/fill/etc. aren't silently lost); (3) anything else logs `console.error` with the received key sample and aborts the install (registry stays unchanged). Net: the documented flat shape from `.claude/docs/guides/02-quick-start.md` continues to work but emits one diagnostic warn per install; consumers on prior versions writing the flat shape needed to wrap manually to get icons at all. Files: `packages/web-components/core/icons.js` (+59 LOC: `WEIGHT_KEYS` const, `isFlatGlobShape()`, `warnedShapes` WeakSet, three-branch dispatch inside `installIconLoaders`).
|
|
1107
1138
|
- **`core/icons-phosphor.js` no longer silently swallows `import.meta.glob` failures (FB-08).** Two silent-fail paths fixed. (a) **Empty-glob path** — `import.meta.glob('/node_modules/@phosphor-icons/core/assets/<weight>/*.svg', …)` returns `{}` (not an error) when zero files match. This happens when the consumer's Vite root sits below `node_modules`, or with pnpm/yarn-berry virtual paths, or when this module is loaded from a published package directory (the absolute-style glob is resolved against the Vite root, not this file's directory). Previously `hasViteGlob` was set true and `installIconLoaders({ regular: {}, … })` ran anyway, leaving the registry empty with no diagnostic. The fix sums per-weight entry counts after the `try` block; if all six weights have zero entries, emits a `console.warn` with the canonical manual-install snippet. (b) **Caught-error path** — the bare `catch {}` was scoped to handle "no Vite at all" (`ReferenceError` because `import.meta.glob` doesn't exist in static serving), but it also swallowed every OTHER error type (plugin order issues, Vite-config misconfigs, etc.). The catch now logs non-`ReferenceError` failures via `console.warn` before falling back to the manifest fetch. Files: `packages/web-components/core/icons-phosphor.js` (+38 LOC, -2 LOC).
|
|
1108
1139
|
|
|
1109
1140
|
### Docs
|
|
1110
|
-
- **Quick-start + migration guide examples corrected (FB-09).**
|
|
1141
|
+
- **Quick-start + migration guide examples corrected (FB-09).** `.claude/docs/guides/02-quick-start.md` lines ~76-81 (boot sequence) and ~126-131 (the dedicated `installIconLoadersForRegistered` section) both showed the flat-glob form passed directly to `installIconLoadersForRegistered`. Both now wrap the glob in `{ regular: … }` to match the canonical contract. New `### Pitfall: flat glob silently auto-promoted (v0.6.15+)` section explains the FB-07 auto-promote behavior and when the per-weight form is strictly required (bold/fill/etc.). `.claude/docs/MIGRATION GUIDE.md` lines ~279-282 (the v0.5.3 §154 recommended upgrade example) had the same flat-glob bug — corrected. The skill `adia-ui-kit` v2.9.0 ships the same scaffold-template correction.
|
|
1111
1142
|
|
|
1112
1143
|
### Verification
|
|
1113
1144
|
- `verify:traits` 56/56 clean.
|
|
@@ -1341,7 +1372,7 @@ Files: `slider.css`, `slider.class.js`, `slider.examples.html`, `slider.yaml`, `
|
|
|
1341
1372
|
|
|
1342
1373
|
## [0.5.15] - 2026-05-16
|
|
1343
1374
|
|
|
1344
|
-
> **Scope note:** §325 + §326 were originally planned as a separate v0.5.16 cycle (see retired
|
|
1375
|
+
> **Scope note:** §325 + §326 were originally planned as a separate v0.5.16 cycle (see retired `.claude/docs/plans/0.5.16-release-plan.md`); absorbed into v0.5.15 since both landed within the same release window (same-day commits prior to bump). The peer's v0.5.16 plan-doc explicitly anticipated this absorption option ("Hermes's call per `/lockstep-release`"). v0.5.16 plan-doc marked SHIPPED-IN-V0.5.15.
|
|
1345
1376
|
|
|
1346
1377
|
### v0.5.15 §326 — `<swatch-ui>` `[slot="chrome"]` lost in template contexts (FB-37; P1)
|
|
1347
1378
|
|
|
@@ -2748,7 +2779,7 @@ Also fixed `code.yaml`: removed a phantom `copy` event declaration (no runtime e
|
|
|
2748
2779
|
|
|
2749
2780
|
### Audit summary — hand-authored `.d.ts` cleanliness as of v0.4.9
|
|
2750
2781
|
|
|
2751
|
-
After §90 + §91b sweeps, **all 17 form-bearing primitives' hand-authored `.d.ts` files are runtime-matched.** Audit recipe captured in
|
|
2782
|
+
After §90 + §91b sweeps, **all 17 form-bearing primitives' hand-authored `.d.ts` files are runtime-matched.** Audit recipe captured in `.claude/docs/plans/0.4.9-release-plan.md` §91b for future cycles — automatable as `scripts/release/check-form-bearing-dts.mjs` in a later cycle if drift returns.
|
|
2752
2783
|
|
|
2753
2784
|
### Documentation — USAGE.md "Derived reactive bindings" subsection (§91d, FEEDBACK-04 #3)
|
|
2754
2785
|
|
|
@@ -3198,7 +3229,7 @@ Companion to the corpus simplification arc in `@adia-ai/a2ui-{runtime,compose,co
|
|
|
3198
3229
|
|
|
3199
3230
|
Catalog (`packages/a2ui/corpus/catalog-a2ui_0_9.json`) regenerated to pick up every yaml addition. `verify:traits` clean at 56/56; `components --verify` clean at 125 files.
|
|
3200
3231
|
|
|
3201
|
-
See root [CHANGELOG.md `[Unreleased]`](../../CHANGELOG.md) for the cross-cutting arc narrative + [docs/journal/2026/05/2026-05-12.md](
|
|
3232
|
+
See root [CHANGELOG.md `[Unreleased]`](../../CHANGELOG.md) for the cross-cutting arc narrative + [.claude/docs/journal/2026/05/2026-05-12.md](../../.claude/docs/journal/2026/05/2026-05-12.md) §§ 43 / 44 / 50 / 51 for per-§ details.
|
|
3202
3233
|
## [0.4.3] - 2026-05-11
|
|
3203
3234
|
|
|
3204
3235
|
### Added
|
|
@@ -3214,7 +3245,7 @@ See root [CHANGELOG.md `[Unreleased]`](../../CHANGELOG.md) for the cross-cutting
|
|
|
3214
3245
|
|
|
3215
3246
|
### Lockstep
|
|
3216
3247
|
|
|
3217
|
-
9-package coordinated PATCH cut to v0.4.3 (per [
|
|
3248
|
+
9-package coordinated PATCH cut to v0.4.3 (per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy)). Internal `@adia-ai/*` dep ranges stay at `^0.4.0` (patch-cut asymmetry — `^0.4.0` covers `0.4.x` under semver). Ratifies [ADR-0027](../../.brain/adrs/0027-cross-primitive-composition-imports.md) — cross-primitive composition imports are the consumer's responsibility; the primitive's `.js` does NOT side-effect-import composed primitives. Source files touched: `components/input/input.{js,css,yaml,a2ui.json}`. See root [CHANGELOG.md `## [0.4.3]`](../../CHANGELOG.md) for the cut narrative.
|
|
3218
3249
|
## [0.4.2] - 2026-05-11
|
|
3219
3250
|
|
|
3220
3251
|
### Changed
|
|
@@ -3251,7 +3282,7 @@ See root [CHANGELOG.md `[Unreleased]`](../../CHANGELOG.md) for the cross-cutting
|
|
|
3251
3282
|
|
|
3252
3283
|
### Lockstep
|
|
3253
3284
|
|
|
3254
|
-
9-package coordinated PATCH cut to v0.4.2 (per [
|
|
3285
|
+
9-package coordinated PATCH cut to v0.4.2 (per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy)). Internal `@adia-ai/*` dep ranges stay at `^0.4.0` (patch-cut asymmetry — `^0.4.0` covers `0.4.x` under semver). ADR-0025 ([`.brain/adrs/0025-no-native-form-controls.md`](../../.brain/adrs/0025-no-native-form-controls.md)) ratified — codifies the "no native or suppressed-native interactive widgets in primitives" principle that the `<input-ui type="number">` rewrite implements; `password` remains the documented exception (physically requires `<input type="password">` for `-webkit-text-security`). See root [CHANGELOG.md `## [0.4.2]`](../../CHANGELOG.md) for the cut narrative.
|
|
3255
3286
|
## [0.4.1] - 2026-05-10
|
|
3256
3287
|
|
|
3257
3288
|
### Ride-along (no source changes)
|
|
@@ -3283,7 +3314,7 @@ Lockstep version bump only — source byte-identical to v0.3.4. Internal `@adia-
|
|
|
3283
3314
|
Lockstep version bump only — source byte-identical to v0.3.3. Internal `@adia-ai/*` dep ranges remain at `^0.3.0`. See root [CHANGELOG.md `## [0.3.4]`](../../CHANGELOG.md) for the cut narrative.
|
|
3284
3315
|
## [0.3.3] - 2026-05-07
|
|
3285
3316
|
|
|
3286
|
-
**Lockstep cut.** All 9 published `@adia-ai/*` packages now share version `0.3.3`, governed by [
|
|
3317
|
+
**Lockstep cut.** All 9 published `@adia-ai/*` packages now share version `0.3.3`, governed by [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy).
|
|
3287
3318
|
|
|
3288
3319
|
### Changed
|
|
3289
3320
|
|
|
@@ -3296,7 +3327,7 @@ Lockstep version bump only — source byte-identical to v0.3.3. Internal `@adia-
|
|
|
3296
3327
|
## [0.3.2] - 2026-05-06
|
|
3297
3328
|
|
|
3298
3329
|
**9-package lockstep patch cut to v0.3.2.** All lockstep members share
|
|
3299
|
-
one version per [
|
|
3330
|
+
one version per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy).
|
|
3300
3331
|
Internal `@adia-ai/*` dep ranges unchanged at `^0.3.0`.
|
|
3301
3332
|
|
|
3302
3333
|
### No source changes
|
|
@@ -3309,7 +3340,7 @@ version only.
|
|
|
3309
3340
|
- `version`: `0.3.1` → `0.3.2`.
|
|
3310
3341
|
## [0.3.1] - 2026-05-06
|
|
3311
3342
|
|
|
3312
|
-
**9-package lockstep patch cut + folder-per-trait restructure.** All 9 published `@adia-ai/*` packages bump 0.3.0 → 0.3.1 per [
|
|
3343
|
+
**9-package lockstep patch cut + folder-per-trait restructure.** All 9 published `@adia-ai/*` packages bump 0.3.0 → 0.3.1 per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy). Internal `@adia-ai/*` dep ranges remain at `^0.3.0` (covers `0.3.1` under semver — patch-cut asymmetry).
|
|
3313
3344
|
|
|
3314
3345
|
This is a **patch cut on top of v0.3.0, no BREAKING changes for npm consumers.** The barrel API (`@adia-ai/web-components/traits`, `@adia-ai/web-components/components`, etc.) is byte-equivalent to v0.3.0 at the public surface. The change is internal: the trait library moved from a flat `traits/<name>.{html,js,examples.html,examples.js,test.js}` layout to one folder per trait (`traits/<name>/<name>.{...}`), mirroring the existing `components/<name>/` convention.
|
|
3315
3346
|
|
|
@@ -3330,7 +3361,7 @@ Symmetry with `components/<name>/` (already folder-per for months) — easier to
|
|
|
3330
3361
|
- `packages/a2ui/compose/transpiler/transpiler-maps.js` — no change since v0.3.0 (the v0.3.0 entry mentioned this file; correction: that update was part of v0.3.0).
|
|
3331
3362
|
## [0.3.0] - 2026-05-05
|
|
3332
3363
|
|
|
3333
|
-
**9-package lockstep cut.** All 9 published `@adia-ai/*` packages bump 0.2.5 → 0.3.0 per [
|
|
3364
|
+
**9-package lockstep cut.** All 9 published `@adia-ai/*` packages bump 0.2.5 → 0.3.0 per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy). Internal `@adia-ai/*` dep ranges bump `^0.2.0` → `^0.3.0`.
|
|
3334
3365
|
|
|
3335
3366
|
The lockstep policy expanded from 8 to 9 packages with this cut — `@adia-ai/llm` joins as a foundational primitive (extracted from `@adia-ai/a2ui-compose/llm`), and `@adia-ai/a2ui-utils` was renamed to `@adia-ai/a2ui-runtime`. Both are BREAKING for npm consumers (acceptable under pre-1.0 semver).
|
|
3336
3367
|
|
|
@@ -3352,7 +3383,7 @@ The following directories saw significant in-repo changes between v0.2.5 and v0.
|
|
|
3352
3383
|
- `patterns/` — no source changes since v0.2.5.
|
|
3353
3384
|
## [0.2.5] - 2026-05-04
|
|
3354
3385
|
|
|
3355
|
-
**Lockstep cut + new `<fields-ui>` form-grid primitive + `draggable-list-item` last-item drop-zone fix.** All 8 published `@adia-ai/*` packages bump 0.2.4 → 0.2.5 per [
|
|
3386
|
+
**Lockstep cut + new `<fields-ui>` form-grid primitive + `draggable-list-item` last-item drop-zone fix.** All 8 published `@adia-ai/*` packages bump 0.2.4 → 0.2.5 per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy). Patch cut — **no BREAKING changes**.
|
|
3356
3387
|
|
|
3357
3388
|
### Added
|
|
3358
3389
|
|
|
@@ -3374,7 +3405,7 @@ The following directories saw significant in-repo changes between v0.2.5 and v0.
|
|
|
3374
3405
|
- `styles/components.css` adds `@import "../components/fields/fields.css"`.
|
|
3375
3406
|
## [0.2.4] - 2026-05-04
|
|
3376
3407
|
|
|
3377
|
-
**Lockstep cut + Tier 4 capability adds + 2 architectural rewrites.** All 8 published `@adia-ai/*` packages bump 0.2.3 → 0.2.4 per [
|
|
3408
|
+
**Lockstep cut + Tier 4 capability adds + 2 architectural rewrites.** All 8 published `@adia-ai/*` packages bump 0.2.3 → 0.2.4 per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy). Patch cut — no breaking changes.
|
|
3378
3409
|
|
|
3379
3410
|
### Changed
|
|
3380
3411
|
|
|
@@ -3384,8 +3415,8 @@ The following directories saw significant in-repo changes between v0.2.5 and v0.
|
|
|
3384
3415
|
- `traits/index.js` adds 12 new exports (the 11 Tier-4 traits + droppable from the parallel Tasks UI initiative); `traits/_catalog.json` regenerated to 56 entries; `core/icons.js` extended with ~25 new aliases.
|
|
3385
3416
|
|
|
3386
3417
|
The substantive content of the next cut, surfaced from the
|
|
3387
|
-
2026-05-04 trait-library lift initiative (
|
|
3388
|
-
|
|
3418
|
+
2026-05-04 trait-library lift initiative (`.claude/docs/PLAN.md`,
|
|
3419
|
+
`.claude/docs/reports/traits-creative-director-audit-2026-05-04.md`).
|
|
3389
3420
|
**No BREAKING changes.** Every public tag, prop, event, and
|
|
3390
3421
|
declarative `traits=` attribute from v0.2.3 still works.
|
|
3391
3422
|
|
|
@@ -3638,7 +3669,7 @@ warnings on every page that referenced these:
|
|
|
3638
3669
|
|
|
3639
3670
|
**Lockstep cut + accumulated fixes.** All 8 published `@adia-ai/*`
|
|
3640
3671
|
packages bump 0.2.2 → 0.2.3 per
|
|
3641
|
-
[
|
|
3672
|
+
[`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy).
|
|
3642
3673
|
Patch cut — no breaking changes. The substantive content is
|
|
3643
3674
|
`web-components`-only; the other 7 packages have no source change.
|
|
3644
3675
|
|
|
@@ -3692,7 +3723,7 @@ edge instead of leaving the column reading as dead width. Per-row
|
|
|
3692
3723
|
---
|
|
3693
3724
|
## [0.2.2] - 2026-05-02
|
|
3694
3725
|
|
|
3695
|
-
**Lockstep cut + trait coverage 100% + `<traits-host>` wrapper.** All 8 published `@adia-ai/*` packages bump 0.2.1 → 0.2.2 per [
|
|
3726
|
+
**Lockstep cut + trait coverage 100% + `<traits-host>` wrapper.** All 8 published `@adia-ai/*` packages bump 0.2.1 → 0.2.2 per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy). Patch cut — no breaking changes.
|
|
3696
3727
|
|
|
3697
3728
|
### Changed
|
|
3698
3729
|
|
|
@@ -3711,7 +3742,7 @@ Follow-up landing on top of the v0.2.1 trait-system work — closes the two foll
|
|
|
3711
3742
|
---
|
|
3712
3743
|
## [0.2.1] - 2026-05-02
|
|
3713
3744
|
|
|
3714
|
-
**Lockstep cut + 41-trait library overhaul + `<stat-ui>` ad-blocker rename.** All 8 published `@adia-ai/*` packages bump 0.2.0 → 0.2.1 per [
|
|
3745
|
+
**Lockstep cut + 41-trait library overhaul + `<stat-ui>` ad-blocker rename.** All 8 published `@adia-ai/*` packages bump 0.2.0 → 0.2.1 per [`.claude/docs/specs/package-architecture.md` § 15](../../.claude/docs/specs/package-architecture.md#15-versioning-policy). Patch cut — no breaking changes.
|
|
3715
3746
|
|
|
3716
3747
|
### Changed
|
|
3717
3748
|
|
|
@@ -3803,8 +3834,8 @@ transition rather than snapping. No JS changes; no API changes.
|
|
|
3803
3834
|
## [0.2.0] - 2026-05-02
|
|
3804
3835
|
|
|
3805
3836
|
**Lockstep cut.** All 8 published `@adia-ai/*` packages now share one
|
|
3806
|
-
version, governed by [
|
|
3807
|
-
(Versioning Policy)](
|
|
3837
|
+
version, governed by [`.claude/docs/specs/package-architecture.md` § 15
|
|
3838
|
+
(Versioning Policy)](../../.claude/docs/specs/package-architecture.md#15-versioning-policy)
|
|
3808
3839
|
and enforced by `npm run check:lockstep` + the
|
|
3809
3840
|
`lockstep-versioning` job in
|
|
3810
3841
|
[`.github/workflows/docs-lint.yml`](../../.github/workflows/docs-lint.yml).
|
package/README.md
CHANGED
|
@@ -117,7 +117,7 @@ web-components/
|
|
|
117
117
|
│ <traits-host> wrapper for raw-HTML declarative
|
|
118
118
|
│ composition. Generated catalog at _catalog.json
|
|
119
119
|
│ drives the MCP get_traits tool + per-trait demo
|
|
120
|
-
│ pages. Full contract in docs/specs/traits.md.
|
|
120
|
+
│ pages. Full contract in .claude/docs/specs/traits.md.
|
|
121
121
|
│
|
|
122
122
|
├── a2ui/ — deprecation shim for one release
|
|
123
123
|
│ └── index.js Re-exports @adia-ai/a2ui-runtime with a
|
|
@@ -247,7 +247,7 @@ class MyPanel extends UIElement {
|
|
|
247
247
|
|
|
248
248
|
The `el` parameter is the element instance — every signal-backed property is reactively read.
|
|
249
249
|
|
|
250
|
-
Full authoring contract: [
|
|
250
|
+
Full authoring contract: [`.claude/docs/specs/component-token-contract.md`](../../.claude/docs/specs/component-token-contract.md).
|
|
251
251
|
The `adia-ui-authoring` skill encodes the 20 non-negotiable rules.
|
|
252
252
|
|
|
253
253
|
## Card-n / drawer-ui composition parity
|
package/USAGE.md
CHANGED
|
@@ -9,17 +9,18 @@ The complete reference for engineers and agents **integrating** AdiaUI into an a
|
|
|
9
9
|
## Contents
|
|
10
10
|
|
|
11
11
|
1. [Install](#install)
|
|
12
|
-
2. [
|
|
13
|
-
3. [
|
|
14
|
-
4. [Property
|
|
15
|
-
5. [
|
|
16
|
-
6. [
|
|
17
|
-
7. [
|
|
18
|
-
8. [
|
|
19
|
-
9. [
|
|
20
|
-
10. [
|
|
21
|
-
11. [
|
|
22
|
-
12. [
|
|
12
|
+
2. [Icons — wiring the registry](#icons--wiring-the-registry)
|
|
13
|
+
3. [The mental model](#the-mental-model)
|
|
14
|
+
4. [Property reactivity (signal-backed)](#property-reactivity-signal-backed)
|
|
15
|
+
5. [Property binding patterns (templates / framework integration)](#property-binding-patterns)
|
|
16
|
+
6. [Event contract — `CustomEvent` with `detail`](#event-contract)
|
|
17
|
+
7. [Form participation — `UIFormElement` + `ElementInternals`](#form-participation)
|
|
18
|
+
8. [Data binding with `data-stream-*`](#data-binding-with-data-stream-)
|
|
19
|
+
9. [Lifecycle — `connected` / `render` / `updated` / `disconnected`](#lifecycle)
|
|
20
|
+
10. [Theming, density, size](#theming-density-size)
|
|
21
|
+
11. [Registration — auto vs explicit](#registration--auto-vs-explicit)
|
|
22
|
+
12. [TypeScript](#typescript)
|
|
23
|
+
13. [Anti-patterns](#anti-patterns)
|
|
23
24
|
|
|
24
25
|
---
|
|
25
26
|
|
|
@@ -96,6 +97,50 @@ For the live demo of every component: <https://ui-kit.exe.xyz/site/components/>.
|
|
|
96
97
|
|
|
97
98
|
---
|
|
98
99
|
|
|
100
|
+
## Icons — wiring the registry
|
|
101
|
+
|
|
102
|
+
`<icon-ui>` (and every component that renders an icon — `<button-ui icon>`,
|
|
103
|
+
`<badge-ui>`, menus, etc.) draws from an **icon registry** that your app
|
|
104
|
+
must wire **once, from your own entry module**. Out of the box the registry
|
|
105
|
+
is empty; an un-wired registry renders every icon **blank**.
|
|
106
|
+
|
|
107
|
+
**Why the app has to do it.** The zero-config glob in the package's own
|
|
108
|
+
`icons-phosphor.js` uses `import.meta.glob('/node_modules/@phosphor-icons/…')`,
|
|
109
|
+
which is a **build-time macro your bundler rewrites** — and under Vite 8 /
|
|
110
|
+
rolldown that rewrite **does not happen for code imported from inside a
|
|
111
|
+
published dependency**. The glob has to be evaluated in *your* source graph.
|
|
112
|
+
`@phosphor-icons/core` ships as a dependency of this package (so the SVG
|
|
113
|
+
assets resolve), but the glob that reads them must live in your app.
|
|
114
|
+
|
|
115
|
+
**The one-time wiring (do this in your app entry, before first paint):**
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
import { installIconLoaders } from '@adia-ai/web-components/core/icons';
|
|
119
|
+
|
|
120
|
+
installIconLoaders({
|
|
121
|
+
regular: import.meta.glob(
|
|
122
|
+
'/node_modules/@phosphor-icons/core/assets/regular/*.svg',
|
|
123
|
+
{ query: '?raw', import: 'default', eager: true },
|
|
124
|
+
),
|
|
125
|
+
// add other weights only if you use them:
|
|
126
|
+
// bold: import.meta.glob('/node_modules/@phosphor-icons/core/assets/bold/*.svg', { query: '?raw', import: 'default', eager: true }),
|
|
127
|
+
// fill: import.meta.glob('/node_modules/@phosphor-icons/core/assets/fill/*.svg', { query: '?raw', import: 'default', eager: true }),
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`installIconLoaders` is idempotent, may be called before or after the
|
|
132
|
+
elements connect (icons already on the page repaint when it runs), and
|
|
133
|
+
accepts either the per-weight map above or a flat `path → svg-string` map
|
|
134
|
+
if you source icons some other way (`registerIcon(name, svg)` /
|
|
135
|
+
`registerIcons(map)` are the lower-level primitives).
|
|
136
|
+
|
|
137
|
+
**Fail-loud, not fail-blank.** If any `<icon-ui name="…">` renders and the
|
|
138
|
+
registry was never wired, the component logs a one-shot `console.error`
|
|
139
|
+
naming this exact fix. A single *missing* icon (registry wired, that one
|
|
140
|
+
name absent) warns separately and does not trip the un-wired error.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
99
144
|
## The mental model
|
|
100
145
|
|
|
101
146
|
Every AdiaUI primitive is a **standard light-DOM custom element**. There's no shadow DOM, no compiler, no framework — just `customElements.define()` extending a small `UIElement` base class. The base class wires a signal-backed property system on top.
|
|
@@ -421,7 +466,7 @@ export class UIModal extends UIElement {
|
|
|
421
466
|
}
|
|
422
467
|
```
|
|
423
468
|
|
|
424
|
-
Reference: [
|
|
469
|
+
Reference: [`.claude/docs/conventions/component-events.md`](../../.claude/docs/conventions/component-events.md) for the 1-page convention summary; [`scripts/build/dts-codegen.mjs`](../../scripts/build/dts-codegen.mjs) for the codegen logic that reads `x-adiaui.events`; [`scripts/release/check-form-bearing-dts.mjs`](../../scripts/release/check-form-bearing-dts.mjs) for the drift audit.
|
|
425
470
|
|
|
426
471
|
---
|
|
427
472
|
|
|
@@ -1586,8 +1631,8 @@ If your design needs label-on-tile (e.g. Tokens Studio's C1.3 hand-rolled `<div
|
|
|
1586
1631
|
- [`README.md`](./README.md) — package overview + authoring guide
|
|
1587
1632
|
- [Component yaml contracts](./components/) — every primitive's complete API (props, events, slots, examples)
|
|
1588
1633
|
- [Live demos](https://ui-kit.exe.xyz/site/components/) — every primitive in action
|
|
1589
|
-
- [
|
|
1590
|
-
- [
|
|
1591
|
-
- [
|
|
1634
|
+
- [`.claude/docs/specs/component-token-contract.md`](../../.claude/docs/specs/component-token-contract.md) — full authoring contract
|
|
1635
|
+
- [`.claude/docs/specs/component-implementation-patterns.md`](../../.claude/docs/specs/component-implementation-patterns.md) — render strategies
|
|
1636
|
+
- [`.claude/docs/specs/traits.md`](../../.claude/docs/specs/traits.md) — composable behaviors
|
|
1592
1637
|
|
|
1593
1638
|
For consumer questions not covered here, file an issue against [adiahealth/gen-ui-kit](https://github.com/adiahealth/gen-ui-kit/issues). This document is the canonical answer — if it doesn't have your answer, it's a doc gap worth fixing.
|
|
@@ -24,6 +24,15 @@
|
|
|
24
24
|
"text": {
|
|
25
25
|
"description": "Header text — the clickable label that toggles the section.",
|
|
26
26
|
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"variant": {
|
|
29
|
+
"description": "Per-item posture override. Items normally inherit their host\naccordion-ui's [variant] — set this directly on ONE item only to\nopt it out of (`flat`) or into (`contained`) the host's posture.",
|
|
30
|
+
"type": "string",
|
|
31
|
+
"enum": [
|
|
32
|
+
"flat",
|
|
33
|
+
"contained"
|
|
34
|
+
],
|
|
35
|
+
"default": "flat"
|
|
27
36
|
}
|
|
28
37
|
},
|
|
29
38
|
"required": [
|
|
@@ -66,6 +75,9 @@
|
|
|
66
75
|
"body": {
|
|
67
76
|
"description": "The section's collapsible content. Renders below the header; hidden when `[open]` is unset. Author-fills with prose, lists, embedded forms, or any rich markup the panel needs."
|
|
68
77
|
},
|
|
78
|
+
"caret": {
|
|
79
|
+
"description": "The disclosure indicator icon. Auto-stamped (a caret-down icon-ui)\nwhen absent — under BOTH the default header and an authored\n[slot=\"header\"]. Author your own [slot=\"caret\"] element (even empty)\nto opt out of the auto-stamp; no separate attribute needed."
|
|
80
|
+
},
|
|
69
81
|
"header": {
|
|
70
82
|
"description": "Custom header content. By default `[text]` renders as a plain header\nlabel, but a `[slot=\"header\"]` override lets consumers author rich\nheaders (icon + title + action buttons + caret)."
|
|
71
83
|
}
|
|
@@ -81,7 +93,24 @@
|
|
|
81
93
|
]
|
|
82
94
|
},
|
|
83
95
|
"tag": "accordion-item-ui",
|
|
84
|
-
"tokens": {
|
|
96
|
+
"tokens": {
|
|
97
|
+
"--accordion-item-bg": {
|
|
98
|
+
"description": "Item surface background.",
|
|
99
|
+
"default": "transparent"
|
|
100
|
+
},
|
|
101
|
+
"--accordion-item-body-pt": {
|
|
102
|
+
"description": "Open body top padding.",
|
|
103
|
+
"default": 0
|
|
104
|
+
},
|
|
105
|
+
"--accordion-item-border": {
|
|
106
|
+
"description": "Item surface border (full shorthand — mirrors --card-border).",
|
|
107
|
+
"default": "none"
|
|
108
|
+
},
|
|
109
|
+
"--accordion-item-divider": {
|
|
110
|
+
"description": "Border between header and open body when expanded.",
|
|
111
|
+
"default": "none"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
85
114
|
"traits": [],
|
|
86
115
|
"version": 1
|
|
87
116
|
}
|
|
@@ -26,6 +26,17 @@ props:
|
|
|
26
26
|
description: Whether the section is expanded.
|
|
27
27
|
type: boolean
|
|
28
28
|
default: false
|
|
29
|
+
variant:
|
|
30
|
+
description: |-
|
|
31
|
+
Per-item posture override. Items normally inherit their host
|
|
32
|
+
accordion-ui's [variant] — set this directly on ONE item only to
|
|
33
|
+
opt it out of (`flat`) or into (`contained`) the host's posture.
|
|
34
|
+
type: string
|
|
35
|
+
default: flat
|
|
36
|
+
enum:
|
|
37
|
+
- flat
|
|
38
|
+
- contained
|
|
39
|
+
reflect: true
|
|
29
40
|
slots:
|
|
30
41
|
header:
|
|
31
42
|
description: |-
|
|
@@ -39,6 +50,12 @@ slots:
|
|
|
39
50
|
`[slot="actions"]`, or marked `[data-no-toggle]`) are excluded from
|
|
40
51
|
the toggle-on-click cascade — clicking them fires their own handler
|
|
41
52
|
without also toggling the section.
|
|
53
|
+
caret:
|
|
54
|
+
description: |-
|
|
55
|
+
The disclosure indicator icon. Auto-stamped (a caret-down icon-ui)
|
|
56
|
+
when absent — under BOTH the default header and an authored
|
|
57
|
+
[slot="header"]. Author your own [slot="caret"] element (even empty)
|
|
58
|
+
to opt out of the auto-stamp; no separate attribute needed.
|
|
42
59
|
body:
|
|
43
60
|
description: >-
|
|
44
61
|
The section's collapsible content. Renders below the header; hidden
|
|
@@ -52,6 +69,20 @@ events:
|
|
|
52
69
|
type: boolean
|
|
53
70
|
description: New open state.
|
|
54
71
|
|
|
72
|
+
tokens:
|
|
73
|
+
--accordion-item-bg:
|
|
74
|
+
description: Item surface background.
|
|
75
|
+
default: transparent
|
|
76
|
+
--accordion-item-border:
|
|
77
|
+
description: Item surface border (full shorthand — mirrors --card-border).
|
|
78
|
+
default: none
|
|
79
|
+
--accordion-item-divider:
|
|
80
|
+
description: Border between header and open body when expanded.
|
|
81
|
+
default: none
|
|
82
|
+
--accordion-item-body-pt:
|
|
83
|
+
description: Open body top padding.
|
|
84
|
+
default: 0
|
|
85
|
+
|
|
55
86
|
keywords:
|
|
56
87
|
- accordion-item
|
|
57
88
|
- collapsible
|
|
@@ -75,3 +106,5 @@ a2ui:
|
|
|
75
106
|
reason: 'Built-in cascade; do not wire onclick yourself.'
|
|
76
107
|
- rule: 'For single-button disclosures (one expanding panel without a list) use <details>/<summary> or compose <button-ui> + <section-ui>.'
|
|
77
108
|
reason: 'Accordion-item assumes sibling-context.'
|
|
109
|
+
- rule: 'An item inherits its host accordion-ui''s [variant]; set variant="flat" or variant="contained" directly on ONE item to override just that item against the host.'
|
|
110
|
+
reason: 'Per-item posture override.'
|
|
@@ -20,6 +20,15 @@
|
|
|
20
20
|
"description": "Allow multiple panels to be open simultaneously",
|
|
21
21
|
"type": "boolean",
|
|
22
22
|
"default": false
|
|
23
|
+
},
|
|
24
|
+
"variant": {
|
|
25
|
+
"description": "Visual posture, inherited by child accordion-item-ui elements unless a\nchild sets its own [variant]. `flat` (default) renders items with no\nchrome — settings pages, FAQ blocks, anywhere the accordion sits\ndirectly on the page canvas. `contained` gives every item a bounded\nsurface (background + border + radius spanning header and open body,\nplus a divider between them when open) — the composition to reach for\nwhen nesting the accordion inside <card-ui>.",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"enum": [
|
|
28
|
+
"flat",
|
|
29
|
+
"contained"
|
|
30
|
+
],
|
|
31
|
+
"default": "flat"
|
|
23
32
|
}
|
|
24
33
|
},
|
|
25
34
|
"required": [
|