@adia-ai/web-components 0.6.49 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +128 -0
- package/components/action-list/action-list.css +1 -1
- package/components/agent-artifact/agent-artifact.class.js +10 -10
- package/components/agent-artifact/agent-artifact.css +1 -1
- package/components/agent-reasoning/agent-reasoning.class.js +52 -1
- package/components/agent-reasoning/agent-reasoning.css +49 -22
- package/components/agent-trace/agent-trace.css +10 -10
- package/components/agent-trace/agent-trace.js +3 -3
- package/components/alert/alert.class.js +8 -1
- package/components/alert/alert.css +13 -1
- package/components/avatar/avatar.a2ui.json +2 -14
- package/components/avatar/avatar.class.js +3 -15
- package/components/avatar/avatar.d.ts +2 -4
- package/components/avatar/avatar.yaml +1 -18
- package/components/breadcrumb/breadcrumb.css +4 -1
- package/components/button/button.a2ui.json +3 -0
- package/components/button/button.css +14 -3
- package/components/button/button.yaml +5 -0
- package/components/calendar-grid/calendar-grid.css +1 -1
- package/components/calendar-picker/calendar-picker.css +5 -2
- package/components/chart/chart.a2ui.json +0 -18
- package/components/chart/chart.class.js +8 -50
- package/components/chart/chart.css +1 -15
- package/components/chart/chart.d.ts +0 -4
- package/components/chart/chart.yaml +0 -24
- package/components/color-input/color-input.css +4 -1
- package/components/combobox/combobox.class.js +11 -0
- package/components/combobox/combobox.css +8 -0
- package/components/date-range-picker/date-range-picker.class.js +5 -1
- package/components/date-range-picker/date-range-picker.css +12 -2
- package/components/datetime-picker/datetime-picker.class.js +3 -0
- package/components/datetime-picker/datetime-picker.css +16 -2
- package/components/empty-state/empty-state.css +11 -4
- package/components/field/field.css +17 -6
- package/components/grid/grid.a2ui.json +5 -0
- package/components/grid/grid.class.js +16 -6
- package/components/grid/grid.css +17 -3
- package/components/grid/grid.d.ts +2 -0
- package/components/grid/grid.yaml +9 -0
- package/components/heatmap/heatmap.class.js +9 -3
- package/components/heatmap/heatmap.css +19 -2
- package/components/image/image.css +4 -1
- package/components/input/input.css +1 -1
- package/components/integration-card/integration-card.class.js +31 -7
- package/components/integration-card/integration-card.test.js +12 -1
- package/components/kbd/kbd.a2ui.json +3 -2
- package/components/kbd/kbd.css +7 -4
- package/components/kbd/kbd.d.ts +2 -2
- package/components/kbd/kbd.yaml +2 -1
- package/components/list/list.class.js +8 -1
- package/components/menu/menu.css +4 -1
- package/components/modal/modal.class.js +10 -1
- package/components/modal/modal.css +9 -0
- package/components/option-card/option-card.a2ui.json +3 -0
- package/components/option-card/option-card.css +44 -19
- package/components/option-card/option-card.yaml +5 -0
- package/components/otp-input/otp-input.css +25 -10
- package/components/page/page.css +64 -11
- package/components/pagination/pagination.class.js +1 -1
- package/components/pagination/pagination.css +9 -1
- package/components/pane/pane.a2ui.json +3 -0
- package/components/pane/pane.class.js +7 -6
- package/components/pane/pane.css +5 -5
- package/components/pane/pane.yaml +6 -0
- package/components/pipeline-status/pipeline-status.css +6 -0
- package/components/popover/popover.css +12 -1
- package/components/preview/preview.css +30 -3
- package/components/progress-row/progress-row.css +3 -1
- package/components/qr-code/qr-code.css +4 -1
- package/components/segmented/segmented.css +4 -1
- package/components/select/select.a2ui.json +1 -1
- package/components/select/select.class.js +63 -7
- package/components/select/select.css +18 -0
- package/components/select/select.yaml +9 -2
- package/components/stack/stack.a2ui.json +12 -1
- package/components/stack/stack.d.ts +2 -2
- package/components/stack/stack.yaml +13 -1
- package/components/stat/stat.a2ui.json +5 -0
- package/components/stat/stat.css +55 -0
- package/components/stat/stat.d.ts +2 -0
- package/components/stat/stat.js +4 -0
- package/components/stat/stat.yaml +9 -0
- package/components/swiper/swiper.class.js +14 -6
- package/components/switch/switch.css +13 -0
- package/components/table/table.a2ui.json +2 -2
- package/components/table/table.css +13 -1
- package/components/table/table.yaml +2 -2
- package/components/time-picker/time-picker.css +4 -1
- package/components/timeline/timeline.class.js +3 -3
- package/components/timeline/timeline.css +23 -5
- package/components/toggle-group/toggle-group.css +4 -1
- package/components/toggle-scheme/toggle-scheme.css +4 -1
- package/components/tree/tree-item.a2ui.json +6 -0
- package/components/tree/tree-item.yaml +13 -1
- package/components/tree/tree.a2ui.json +3 -3
- package/components/tree/tree.class.js +24 -9
- package/components/tree/tree.css +8 -8
- package/components/tree/tree.test.js +52 -0
- package/components/tree/tree.yaml +4 -4
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +84 -84
- package/package.json +3 -3
- package/styles/api/layout.css +7 -0
- package/styles/api/text.css +9 -5
- package/styles/index.css +11 -2
- package/styles/prose.css +8 -0
- package/styles/resets.css +5 -5
- package/styles/themes.css +8 -1
- package/styles/tokens.css +3 -3
- package/styles/type/elements.css +73 -0
- package/styles/type/roles.css +14 -49
- package/styles/type/scale.css +0 -5
- package/styles/typography.css +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,133 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
2
|
|
|
3
|
+
## [0.7.0] — 2026-05-31
|
|
4
|
+
|
|
5
|
+
### Added — component features from the docs-QA pass
|
|
6
|
+
|
|
7
|
+
- **`<stat-ui bleed>`** — horizontal-bleed KPI tile. With a `slot="chart"` child, value/label/change stack on the left while the chart fills the right column at full height and bleeds to the card's top/right/bottom edges (the horizontal counterpart to a chart in a `<section bleed>`). First-class reflected Boolean attr (yaml + `static properties`; not a `data-*` hook).
|
|
8
|
+
- **`<page-ui>` region model** — `--page-inset` vertical rhythm between `header`/`section`/`footer` children + `[bleed]` (edge-to-edge, cancels the page `[padding]`) + `section[padding]` (padded sub-surface), mirroring card-ui's section model. The docs promised `@scope` styled the regions but no such rules existed — regions stacked with zero spacing.
|
|
9
|
+
- **`<timeline-ui>` `--timeline-marker-box-size`** — unified marker footprint (1rem; 0.875rem at `size=sm`) the dot/icon/spinner center within; icon-mode chips gain a ring (`--timeline-icon-border`) so they read as markers even when the muted fill blends with the surface.
|
|
10
|
+
- **`<integration-card-ui>` provider→icon fallback** — a card with only `[provider]` (no `[logo]`) now renders a per-provider Phosphor glyph (slack→chat-circle, github→git-branch, …) or a generic `plug`, instead of a blank logo disc.
|
|
11
|
+
- **`<kbd-ui>` `size="lg"`** — added the missing `lg` to the size enum (CSS + docs already shipped three sizes; the yaml capped at sm/md).
|
|
12
|
+
|
|
13
|
+
### Fixed — docs-QA pass (browser-verified)
|
|
14
|
+
|
|
15
|
+
- **`<datetime-picker-ui>`** — committed value now uses the picker-family value color (`--a-ui-text`, bright) + `space-between` alignment (value left, caret right), matching input-ui/select-ui/time-picker (was a centered, dim default button); `[data-has-value]` gates the brightening.
|
|
16
|
+
- **`<kbd-ui>`** — `md` glyph was `--a-ui-tiny` (10px), identical to `sm`; now `--a-ui-xs` (12px) for a real 10/12/14 sm/md/lg ramp.
|
|
17
|
+
- **`<empty-state-ui>`** — heading moved from `--a-ui-lg` (15px control-label ramp; only 1.07× the description) to `--a-heading-md` (17px → 1.21×); the `[minimal]` inline variant keeps the heading bolder + non-muted so it stays distinct from the description.
|
|
18
|
+
- **`<heatmap-ui>`** — `type="day-grid"` keeps fixed cell tracks + scrolls horizontally (GitHub-contributions model) instead of crushing fixed cells into an overlapping smear in narrow containers; `matrix`/`density` keep fitting-and-shrinking.
|
|
19
|
+
- **`<option-card-ui>` `layout="tile"`** — DOM-order-independent (via `order`) with the radio pinned to the card's top-right (cleared the base `grid-area:indicator` that stranded it in a collapsed 8px gutter); token-driven padding. Fixes plan-picker's tile cards.
|
|
20
|
+
- **`<preview-ui>` form-demo width** — the docs render cell capped `<field-ui>` at `max-width:28rem` (448px) together with bare form controls; since field-ui is a full-width form _row_ (its own CSS is `width:100%`), the cap stranded it mid-cell, reading as "not using the available space" on wide single-block demos. Split the rule: field-ui now fills the stage (no cap); bare atomic controls (input/select/combobox/textarea/tags-input/color-input) keep the 28rem measure cap so a lone control doesn't sprawl. (bug-55 follow-up)
|
|
21
|
+
|
|
22
|
+
### Changed — demos + corpus hygiene (docs-QA pass)
|
|
23
|
+
|
|
24
|
+
- **`<field-ui>` demos** — migrated in-chrome affordances (copy / clear / ⌘K) onto `input-ui`'s `leading`/`trailing` slots (inside the input box); field's `trailing`/`action` reserved for beside-field captions + submit buttons. Slots table + A2UI guidance now state the boundary. Short in-chrome _status_ text (e.g. "Required") now uses `input-ui`'s `suffix`/`prefix` attribute rather than a `<span slot="trailing">` _outside_ the input — keeps the status inside the field chrome and lets the input fill the full field width (demo `field-default-trailing-caption` → `field-default-inchrome-required`). (bug-55)
|
|
25
|
+
- **`<inline-edit-ui>` form-participation demo** — key-labelled rows (title/description) + instructional placeholder so the form-field semantics are legible.
|
|
26
|
+
- **`<integration-card-ui>` CRUD-drawer demo** — fixed an invisible drawer: the demo used `side="trailing"`, which is not in the `drawer-ui` `side` enum (`left|right|top|bottom`), so the panel `showModal()`'d but rendered at `opacity:0` collapsed in the top-left. Switched to `side="right"`. (bug-50)
|
|
27
|
+
- **Dead `size="sm"` swept** off layout primitives (`row-ui`/`col-ui`/`grid-ui`) + bare `<span slot="action">` across `patterns/` demos (68 sites repo-wide) — the attribute is a no-op on those tags and polluted the gen-UI corpus.
|
|
28
|
+
- **`dist/` CDN bundles regenerated** (`web-components.min.css` + `web-components.min.js`) for the docs-QA CSS/JS changes + the breaking removals.
|
|
29
|
+
|
|
30
|
+
### Removed (BREAKING) — `<avatar-ui name="…">` deprecated alias retired
|
|
31
|
+
|
|
32
|
+
- **`<avatar-ui>` no longer accepts the `name` attribute** — use `text` instead.
|
|
33
|
+
`name` was a deprecated alias for `text` since 0.4.x (`deprecated_since: "0.4.x"`,
|
|
34
|
+
scheduled for v0.6.0; the codebase reached v0.6.50 still carrying it). Retired in
|
|
35
|
+
full: removed from `avatar.yaml`, the `static properties` map + `displayName`
|
|
36
|
+
fallback + the one-shot deprecation `console.warn` + the `#nameWarned` flag in
|
|
37
|
+
`avatar.class.js`, the `name: string` typing in `avatar.d.ts`, and the
|
|
38
|
+
regenerated `avatar.a2ui.json` sidecar. The `<img>` `alt` now derives from
|
|
39
|
+
`displayName` (= `text`). **Migration:** `<avatar-ui name="Ada">` →
|
|
40
|
+
`<avatar-ui text="Ada">`. No in-repo markup, demo, or corpus chunk used the
|
|
41
|
+
alias (the corpus was swept long ago; the one stray demo was fixed in
|
|
42
|
+
`d3b482c61`). _Pre-1.0 breaking change — bump MINOR on the next cut._
|
|
43
|
+
|
|
44
|
+
### Removed (BREAKING) — `<chart-ui>` `aspect` + `heading` retired (OD-CHART-02)
|
|
45
|
+
|
|
46
|
+
- **`<chart-ui>` no longer accepts `aspect` or `heading`** — both were
|
|
47
|
+
deprecated-but-functional with no removal date; retired across yaml + class.js +
|
|
48
|
+
d.ts + css + sidecar.
|
|
49
|
+
- **`aspect`** (`std`/`wide`/`square`/`tall` — derived the chart's implicit
|
|
50
|
+
height from width): charts without an explicit height now always use the
|
|
51
|
+
standard 4:3 ratio (the prior default, so default charts are unchanged; only
|
|
52
|
+
explicit `aspect="wide|square|tall"` changes). **Migration:** size the chart
|
|
53
|
+
via its parent (width/height on the enclosing card/container).
|
|
54
|
+
- **`heading`** (rendered a title element + fed `aria-label`): **Migration:** put
|
|
55
|
+
the visual title in an enclosing `card-ui` `<header><span slot="heading">`; for
|
|
56
|
+
a descriptive accessible name set `aria-label` directly. With neither,
|
|
57
|
+
`aria-label` now falls back to `"<type> chart"` (e.g. "bar chart"). Verified:
|
|
58
|
+
69 demo charts render, 0 console errors. _Pre-1.0 breaking — bump MINOR._
|
|
59
|
+
|
|
60
|
+
### Removed — `<avatar-ui size>` long-form aliases (were non-functional)
|
|
61
|
+
|
|
62
|
+
- **`<avatar-ui size>` drops `small`/`medium`/`large`/`xlarge`** — use the
|
|
63
|
+
canonical `xs`/`sm`/`md`/`lg`/`xl`. These were declared in `avatar.yaml` +
|
|
64
|
+
`avatar.d.ts` "for back-compat" but had **no CSS implementation** (`avatar.css`
|
|
65
|
+
only defines `:scope[size="xs|sm|md|lg|xl"]`), so `size="small"` silently
|
|
66
|
+
rendered at the base default size — they never worked. Runtime behavior is
|
|
67
|
+
unchanged; this removes the misleading values from the typed API + the sidecar
|
|
68
|
+
the LLM prompt builder reads (training-data noise). No in-repo markup used them.
|
|
69
|
+
|
|
70
|
+
### Changed — global styles assigned to `@layer` cascade layers (ADR-0038)
|
|
71
|
+
|
|
72
|
+
- `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).
|
|
73
|
+
- **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 + `docs/specs/cascade-layer-architecture.md`.
|
|
74
|
+
|
|
75
|
+
### Added — `<select-ui>` per-option `icon` / `avatar`, reflected in the trigger
|
|
76
|
+
|
|
77
|
+
- **`components/select/{select.class.js,select.css,select.yaml}`** — `<option>` now accepts `icon` (Phosphor name) and `avatar` (image URL): `<option value="light" icon="sun">`. Each option renders its glyph in the listbox row **and** the trigger reflects the **selected** option's icon/avatar (theme pickers, assignee/account switchers). Previously a host-level `[icon]` was static — selecting "Light" still showed the fixed `moon`. `#parseOptions` now captures `icon`/`avatar` from declarative `<option>`/`<optgroup>` children (and the `.options` array shape gains `icon?`/`avatar?`); a new `#syncLeading()` reconciles the trigger's `[slot="leading"]` to the selected option on every render (avatar beats icon; host `[icon]`/`[avatar]` is the fallback). Only manages the component-stamped trigger (`[data-select-leading]`) — a consumer-custom trigger owns its own leading. Multi-select is unaffected (chips). +CSS for `[role="option"] img[data-option-avatar]`; sidecar regenerated. Verified in-browser: trigger shows `sun` for selected "Light", updates to `moon` on selecting "Dark"; per-option avatars render in trigger + rows; 21/21 unit tests green.
|
|
78
|
+
|
|
79
|
+
### Changed — block-level display by default + universal `[inline]` attribute (ADR-0037)
|
|
80
|
+
|
|
81
|
+
- 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 + `docs/specs/attribute-api-system.md` §5.
|
|
82
|
+
|
|
83
|
+
### Changed — `chevron` → `caret` terminology sweep (FEEDBACK-90, ADR-0036 follow-up)
|
|
84
|
+
|
|
85
|
+
- Renamed residual `chevron` terminology to `caret` across 14 component files so the codebase carries one vocabulary (matching the `slot="caret"` convention + the Phosphor `caret-*` icon names). **`agent-artifact`** is the only behavioral surface: `[data-artifact-chevron]` → `[data-artifact-caret]` + `#chevronEl` → `#caretEl` (internal-render collapse indicator — a data-attr styling hook, not a slot, same as `agent-trace`/`agent-reasoning`). The rest is comment/description terminology (`timeline`; `table`/`select` yaml + regenerated a2ui descriptions; `input`/`pagination`/`action-list`/`calendar-grid`/`calendar-picker` comments). **Carve-out:** kept breadcrumb's `data-chunk="…-chevron-sep"` corpus identifier — the separator is semantically a chevron, not a disclosure caret, and renaming a harvested chunk name is a separate re-harvest. No consumer-facing behavior change.
|
|
86
|
+
|
|
87
|
+
### Fixed — form-field demos collapsed to content-width in `<preview-ui>` (demos)
|
|
88
|
+
|
|
89
|
+
- **`components/preview/preview.css`** — a `<field-ui>` (and bare text-field controls) is a flex item in the render cell, so form-field demos sized to their content — a placeholder-only `combobox-ui` shrank to a ~52px "Sel…" stub (input/select were also content-width, just less obvious). The render cell now stretches `field-ui` + text-field controls (`input-ui`/`select-ui`/`combobox-ui`/`textarea-ui`/`tags-input-ui`/`color-input-ui`) to the cell width, capped at `28rem` so single-block stages don't sprawl. Lifts **every** form-field demo to a realistic width at once (combobox 52→202px rows / 448px single-block); non-form demos (buttons, badges, …) keep content-width. Verified 0 console errors across 12 component + pattern pages.
|
|
90
|
+
|
|
91
|
+
### Fixed — `<combobox-ui>` `[size]` didn't step the field height
|
|
92
|
+
|
|
93
|
+
- **`components/combobox/combobox.css`** — the editable `[data-input]` span picked up `8px` block padding from an outer source that out-cascaded the `@scope` rule, pinning the field to ~36px at **every** `[size]` (sm/md/lg measured 36.2 / 37.6 / 39px — barely distinguishable). A higher-specificity guard (`combobox-ui [data-field] [data-input] { padding-block: 0 }`) zeroes it so the field height tracks `--a-size` like `input-ui`/`select-ui` — now **24 / 30 / 36px** for sm/md/lg. (The 8px source isn't in combobox/global/inline CSS — likely a leaked reset or a `contenteditable="plaintext-only"` behavior; flagged for a follow-up audit.)
|
|
94
|
+
|
|
95
|
+
### Added — `<combobox-ui>` demo depth (demos)
|
|
96
|
+
|
|
97
|
+
- **`components/combobox/combobox.examples.html`** — +5 attribute sections closing the depth gap surfaced by the demo-coverage audit (was ~7/17 demonstrable attributes): `prefix`/`suffix` slot (search-icon prefix), `highlight-match`, `loading`, `disabled`, `readonly`. All render correctly now that the width fix above is in place (the prefix demo had appeared collapsed only because of the content-width bug).
|
|
98
|
+
|
|
99
|
+
### Fixed — `<alert-ui>` `slot="action"` rendered wedged between icon and message
|
|
100
|
+
|
|
101
|
+
- **`components/alert/alert.css`** — a trailing `[slot="action"]` button rendered on the **left** (between the leading icon and the message) instead of trailing right, contradicting the documented "right-aligned trailing affordance." Cause: `alert.js` appends the auto-stamped `[slot="content"]`/`[slot="leading"]` *after* any author-provided action button, and the standard render path (unlike the dunning path) gave the action/close slots no `order`, so they sorted in DOM order. Added explicit `order: 1` (action) + `order: 2` (close) so the layout is always `icon → content → action → close`, with content's `flex: 1` pushing both affordances to the trailing edge. Latent since the feature shipped — first exercised by the new demo (no prior `alert-ui` consumer used `slot="action"`). Verified via DOM geometry probe (`iconX < contentX < actionX ≤ closeX`).
|
|
102
|
+
|
|
103
|
+
### Fixed — `<alert-ui>` dunning `due-at` showed the previous calendar day
|
|
104
|
+
|
|
105
|
+
- **`components/alert/alert.class.js`** — `#formatDueDate()` parsed a date-only ISO string (`"2026-05-20"`) as UTC midnight, which a behind-UTC locale then formatted as the *previous* day ("May 19"). Date-only strings are now pinned to local midnight (`"…T00:00:00"`) so the authored calendar day is preserved; full timestamps (with time/offset) keep their exact instant. Invisible in jsdom (UTC) — only manifested in a real browser, so the lenient existing tests (`/May/`, `/2026/`) stayed green (30/30); also corrects the shared `billing-overview` dunning banner.
|
|
106
|
+
|
|
107
|
+
### Added — `<alert-ui>` demo depth (demos)
|
|
108
|
+
|
|
109
|
+
- **`components/alert/alert.examples.html`** — +3 sections taking attribute coverage 33% → **100%** (demo-coverage audit): `title`+`description` (two-line headline/body), `action slot` (trailing button), and the full `dunning` payment-failed pattern (SPEC-006 — `pattern`/`amount`/`currency`/`due-at`/`card-last4`/`reason` across all four reasons + a warning grace-period), plus the `dismissible` alias. Props/Events/Slots tables extended to document the dunning API (`actions` slot, `dunning-action` event). Grounded against SPEC-006 + the real `billing-overview` consumer; surfaced the two `alert-ui` fixes above.
|
|
110
|
+
|
|
111
|
+
### Fixed — `<switch-ui>` `[hint]` rendered beside the label instead of below
|
|
112
|
+
|
|
113
|
+
- **`components/switch/switch.css`** — the `[hint]` caption is documented (yaml + props table + the rule's own comment "Caption beneath the toggle row") as rendering BELOW the label, but the base `inline-flex` row laid the stamped `[slot="hint"]` out as a third inline item beside the label. A `:has([slot="hint"])`-scoped `flex-wrap` + `flex-basis: 100%` now wraps the hint onto its own full-width line, indented under the label. No display-model change (stays `inline-flex`); hint-less switches are 100% unchanged (the hint span is stamped only when `[hint]` is set). Latent since §184 — surfaced by the demo-depth pass.
|
|
114
|
+
|
|
115
|
+
### Fixed — `<list-ui>` `[selectable]` selection chrome was never applied (upgrade race)
|
|
116
|
+
|
|
117
|
+
- **`components/list/list.class.js`** — `selectable` + `selected-key` set no visual selection (`aria-selected` null on every row). Light-DOM upgrade race: `render()`'s `#items()` filtered children by `role="listitem"`, but each `<list-item-ui>` sets that role in its OWN `connected()`, which hasn't run when the parent first `render()`s → `#items()` returned `[]` → `aria-selected` never stamped → the `[aria-selected="true"]` selection CSS never matched. `#items()` now also matches by tag name (`LIST-ITEM-UI`, present pre-upgrade); the attribute persists through the child's later upgrade. Latent since the selection feature shipped (no demo exercised it); +0 test changes, 5/5 green.
|
|
118
|
+
|
|
119
|
+
### Added — primitive demo-depth wave, Phase 3 (demos)
|
|
120
|
+
|
|
121
|
+
- Drove six audit-`critical` primitives to full attribute coverage (demo-coverage audit), each authored from source/spec grounding and browser-probed (0 console errors, visual QA): **`swatch`** 27% → 100% (detail/copyable/copy-value, badge gamut pips, selectable/selected, label-position overlay + auto-contrast); **`color-picker`** 44% → 100% (OKLCH generation constraints — max-chroma / min-l·max-l / base-hue·hue-drift-max — plus corrected the `format` demo to the real `[hex, oklch]` enum and dropped a non-existent `required` prop from its table); **`switch`** 43% → 100% (hint, name/value/required); **`list`** 40% → 100% (contained, selectable/selected-key, + real `selection-change` event docs); **`context-menu`** 33% → 100% (open, long-press-ms); **`toggle-scheme`** 33% → 92% (scoped `target` + icon/label-light/dark + color + storage-prefix; the read-only reflected `active-scheme` is intentionally not authored, + corrected two table defaults vs yaml). Demo-only `examples.html` changes except the two `switch`/`list` fixes above.
|
|
122
|
+
|
|
123
|
+
## [0.6.50] — 2026-05-30
|
|
124
|
+
|
|
125
|
+
### Changed — `slot="caret"` disclosure-indicator convention + FEEDBACK-89 (ADR-0036)
|
|
126
|
+
|
|
127
|
+
- **`components/tree/` (`tree-item-ui`) + `components/pane/` (`pane-ui`)** — renamed the expand/collapse indicator slot `slot="chevron"` → **`slot="caret"`** (and tokens `--*-chevron-*` → `--*-caret-*`, e.g. `--tree-caret-size`, `--pane-caret-fg`), standardizing on the slot name already used by `accordion-item-ui` / `nav-group-ui` / `select-ui` and matching the Phosphor `caret-*` icon vocabulary. **No backward-compat alias** (hard rename; the caret is auto-stamped, so blast radius is small). See [ADR-0036](../../.brain/adrs/0036-caret-slot-disclosure-convention.md).
|
|
128
|
+
- **`tree-item-ui` adopt-or-stamp (FEEDBACK-89)** — `#stamp()` now adopts a consumer's declarative `slot="caret"` and `slot="actions"` children into the auto-stamped row instead of leaving them as siblings below it. A `<button-ui slot="actions">` (the natural way to add a per-row action — add / rename / overflow) now lands inline in the styled, hover-revealed actions area. The host `#onClick` already excludes `[slot="actions"] *` from row selection, so adoption is click-safe. +3 unit tests.
|
|
129
|
+
- **`dist/` CDN bundles** (`web-components.min.css` + `web-components.min.js`) regenerated to carry the renamed `--*-caret-*` tokens + caret stamp logic.
|
|
130
|
+
|
|
3
131
|
## [0.6.49] — 2026-05-30
|
|
4
132
|
|
|
5
133
|
### Changed — card-ui header slot sweep + `nav-group-ui` fixes (demos)
|
|
@@ -98,7 +98,7 @@ action-item-ui:hover [slot="icon"] {
|
|
|
98
98
|
text-overflow: ellipsis;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
/* Default slot (trailing content: kbd, badge,
|
|
101
|
+
/* Default slot (trailing content: kbd, badge, caret) pushed to far right */
|
|
102
102
|
& > :not([slot="icon"]):not([slot="text"]) {
|
|
103
103
|
flex-shrink: 0;
|
|
104
104
|
margin-inline-start: auto;
|
|
@@ -58,7 +58,7 @@ export class UIAgentArtifact extends UIElement {
|
|
|
58
58
|
tone: { type: String, default: 'neutral', reflect: true },
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
// §205 (v0.5.7): dynamic
|
|
61
|
+
// §205 (v0.5.7): dynamic caret icons stamped on collapse/expand state
|
|
62
62
|
// transition (agent-artifact.class.js:119+188). Per FEEDBACK-16 §1 + §209 slot-11 ternary-
|
|
63
63
|
// walker discovery. Note: `this.icon` consumer-supplied — not declared here.
|
|
64
64
|
static requiredIcons = ['caret-right', 'caret-down'];
|
|
@@ -69,7 +69,7 @@ export class UIAgentArtifact extends UIElement {
|
|
|
69
69
|
#iconEl = null;
|
|
70
70
|
#titleEl = null;
|
|
71
71
|
#kindEl = null;
|
|
72
|
-
#
|
|
72
|
+
#caretEl = null;
|
|
73
73
|
#bodyEl = null;
|
|
74
74
|
|
|
75
75
|
connected() {
|
|
@@ -80,7 +80,7 @@ export class UIAgentArtifact extends UIElement {
|
|
|
80
80
|
this.#headerEl?.removeEventListener('click', this.#onHeaderClick);
|
|
81
81
|
this.#headerEl?.removeEventListener('keydown', this.#onHeaderKey);
|
|
82
82
|
this.#headerEl = this.#iconEl = this.#titleEl = null;
|
|
83
|
-
this.#kindEl = this.#
|
|
83
|
+
this.#kindEl = this.#caretEl = this.#bodyEl = null;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
#onHeaderClick = (e) => {
|
|
@@ -120,8 +120,8 @@ export class UIAgentArtifact extends UIElement {
|
|
|
120
120
|
this.#kindEl.setAttribute('variant', TONE_TO_BADGE_VARIANT[this.tone] || 'default');
|
|
121
121
|
this.#kindEl.hidden = !this.kind;
|
|
122
122
|
}
|
|
123
|
-
if (this.#
|
|
124
|
-
this.#
|
|
123
|
+
if (this.#caretEl) {
|
|
124
|
+
this.#caretEl.setAttribute('name', this.collapsed ? 'caret-right' : 'caret-down');
|
|
125
125
|
}
|
|
126
126
|
if (this.#bodyEl) {
|
|
127
127
|
this.#bodyEl.hidden = this.collapsed;
|
|
@@ -187,12 +187,12 @@ export class UIAgentArtifact extends UIElement {
|
|
|
187
187
|
for (const btn of secondaryBtns) actions.appendChild(btn);
|
|
188
188
|
for (const btn of primaryBtns) actions.appendChild(btn);
|
|
189
189
|
|
|
190
|
-
this.#
|
|
191
|
-
this.#
|
|
192
|
-
this.#
|
|
193
|
-
this.#
|
|
190
|
+
this.#caretEl = document.createElement('icon-ui');
|
|
191
|
+
this.#caretEl.setAttribute('color', 'muted');
|
|
192
|
+
this.#caretEl.setAttribute('data-artifact-caret', '');
|
|
193
|
+
this.#caretEl.setAttribute('name', this.collapsed ? 'caret-right' : 'caret-down');
|
|
194
194
|
|
|
195
|
-
this.#headerEl.append(this.#iconEl, this.#titleEl, this.#kindEl, actions, this.#
|
|
195
|
+
this.#headerEl.append(this.#iconEl, this.#titleEl, this.#kindEl, actions, this.#caretEl);
|
|
196
196
|
|
|
197
197
|
// Body
|
|
198
198
|
this.#bodyEl = document.createElement('div');
|
|
@@ -105,6 +105,8 @@ export class UIAgentReasoning extends UIElement {
|
|
|
105
105
|
#summaryEl = null;
|
|
106
106
|
#bodyEl = null;
|
|
107
107
|
#bound = false;
|
|
108
|
+
#resizeObserver = null;
|
|
109
|
+
#spineRaf = 0;
|
|
108
110
|
|
|
109
111
|
get entries() { return this.#entries; }
|
|
110
112
|
|
|
@@ -114,6 +116,19 @@ export class UIAgentReasoning extends UIElement {
|
|
|
114
116
|
this.#startTime = Date.now();
|
|
115
117
|
this.#timerInterval = setInterval(() => this.#tickTimers(), 1000);
|
|
116
118
|
this.#buildShell();
|
|
119
|
+
// Re-measure the connector spine when row heights shift (text reflow on
|
|
120
|
+
// resize moves the dot Ys). The spine writes only absolutely-positioned
|
|
121
|
+
// ::before vars, so observing the host can't feed back into a resize loop.
|
|
122
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
123
|
+
this.#resizeObserver = new ResizeObserver(() => {
|
|
124
|
+
if (this.#spineRaf) return;
|
|
125
|
+
this.#spineRaf = requestAnimationFrame(() => {
|
|
126
|
+
this.#spineRaf = 0;
|
|
127
|
+
this.#layoutSpine();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
this.#resizeObserver.observe(this);
|
|
131
|
+
}
|
|
117
132
|
}
|
|
118
133
|
|
|
119
134
|
// Single delegated handler for every nested timeline-item's toggle event.
|
|
@@ -136,6 +151,12 @@ export class UIAgentReasoning extends UIElement {
|
|
|
136
151
|
clearTimeout(this.#finishTimer);
|
|
137
152
|
this.#finishTimer = null;
|
|
138
153
|
}
|
|
154
|
+
if (this.#spineRaf) {
|
|
155
|
+
cancelAnimationFrame(this.#spineRaf);
|
|
156
|
+
this.#spineRaf = 0;
|
|
157
|
+
}
|
|
158
|
+
this.#resizeObserver?.disconnect();
|
|
159
|
+
this.#resizeObserver = null;
|
|
139
160
|
this.#summaryEl?.removeEventListener('click', this.#onSummaryClick);
|
|
140
161
|
this.#summaryEl?.removeEventListener('keydown', this.#onSummaryKey);
|
|
141
162
|
this.#bodyEl?.removeEventListener('timeline-toggle', this.#onStepToggle);
|
|
@@ -379,7 +400,7 @@ export class UIAgentReasoning extends UIElement {
|
|
|
379
400
|
<span data-reasoning-meta>
|
|
380
401
|
${total ? `<span data-reasoning-counter>${done}/${total}</span>` : ''}
|
|
381
402
|
<span data-reasoning-time>${elapsed}s</span>
|
|
382
|
-
<icon-ui name="${this.collapsed ? 'caret-right' : 'caret-up'}" color="muted" data-reasoning-
|
|
403
|
+
<icon-ui name="${this.collapsed ? 'caret-right' : 'caret-up'}" color="muted" data-reasoning-caret></icon-ui>
|
|
383
404
|
</span>
|
|
384
405
|
`;
|
|
385
406
|
|
|
@@ -404,6 +425,36 @@ export class UIAgentReasoning extends UIElement {
|
|
|
404
425
|
this.#bodyEl.appendChild(this.#renderNonStep(entry));
|
|
405
426
|
}
|
|
406
427
|
}
|
|
428
|
+
|
|
429
|
+
this.#layoutSpine();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Draw one continuous connector line down the marker column from the first
|
|
433
|
+
// step dot to the last — bridging plan / thought / iteration interstitials
|
|
434
|
+
// that otherwise fragment the per-block timeline connectors into stubs. The
|
|
435
|
+
// endpoints are measured (not pure CSS) because interstitial row heights are
|
|
436
|
+
// dynamic; the per-item connectors are suppressed in CSS (the spine owns the
|
|
437
|
+
// line). No spine for 0–1 dots (nothing to connect → no trailing line).
|
|
438
|
+
#layoutSpine() {
|
|
439
|
+
const body = this.#bodyEl;
|
|
440
|
+
if (!body) return;
|
|
441
|
+
if (this.collapsed) { body.removeAttribute('data-spine'); return; }
|
|
442
|
+
const items = body.querySelectorAll('timeline-item-ui');
|
|
443
|
+
if (items.length < 2) { body.removeAttribute('data-spine'); return; }
|
|
444
|
+
|
|
445
|
+
const bodyTop = body.getBoundingClientRect().top;
|
|
446
|
+
// Dot center within an item = top:(1.4em − dot)/2 + 1px + dot/2 = 0.7em + 1px
|
|
447
|
+
// (the dot size cancels), where em is the item's computed font-size.
|
|
448
|
+
const dotY = (el) => {
|
|
449
|
+
const r = el.getBoundingClientRect();
|
|
450
|
+
const fs = parseFloat(getComputedStyle(el).fontSize) || 14;
|
|
451
|
+
return (r.top - bodyTop) + 0.7 * fs + 1;
|
|
452
|
+
};
|
|
453
|
+
const top = dotY(items[0]);
|
|
454
|
+
const height = Math.max(0, dotY(items[items.length - 1]) - top);
|
|
455
|
+
body.style.setProperty('--reasoning-spine-top', `${Math.round(top)}px`);
|
|
456
|
+
body.style.setProperty('--reasoning-spine-h', `${Math.round(height)}px`);
|
|
457
|
+
body.setAttribute('data-spine', '');
|
|
407
458
|
}
|
|
408
459
|
|
|
409
460
|
#makeTimeline() {
|
|
@@ -122,35 +122,56 @@
|
|
|
122
122
|
grid-template-columns: subgrid;
|
|
123
123
|
grid-column: 1 / -1;
|
|
124
124
|
row-gap: var(--agent-reasoning-gap-row, var(--agent-reasoning-gap-row-default));
|
|
125
|
+
position: relative;
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
[data-reasoning-body][hidden] { display: none; }
|
|
128
129
|
|
|
130
|
+
/* ═══════ Connector spine ═══════
|
|
131
|
+
A single continuous line down the marker column from the first step dot to
|
|
132
|
+
the last, bridging plan / thought / iteration interstitials so the run
|
|
133
|
+
reads as one timeline rather than fragmented per-block stubs. Endpoints are
|
|
134
|
+
JS-measured into --reasoning-spine-top / -h (#layoutSpine) — interstitial
|
|
135
|
+
heights are dynamic, so pure CSS can't place them. The x matches the step
|
|
136
|
+
dot center (timeline-item uses var(--timeline-marker-w, 1.25rem) for its
|
|
137
|
+
dot math). Sits behind the dots (z-index 0 < the dots' z-index 1). The
|
|
138
|
+
per-item timeline connectors are suppressed below so they don't double-draw. */
|
|
139
|
+
[data-reasoning-body][data-spine]::before {
|
|
140
|
+
content: '';
|
|
141
|
+
position: absolute;
|
|
142
|
+
left: calc(var(--timeline-marker-w, 1.25rem) / 2 - var(--agent-reasoning-line-w, 1.5px) / 2);
|
|
143
|
+
top: var(--reasoning-spine-top, 0);
|
|
144
|
+
height: var(--reasoning-spine-h, 0);
|
|
145
|
+
width: var(--agent-reasoning-line-w, 1.5px);
|
|
146
|
+
background: var(--agent-reasoning-border, var(--agent-reasoning-border-default));
|
|
147
|
+
z-index: 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
129
150
|
/* All direct children of body span the grid */
|
|
130
151
|
[data-reasoning-body] > * {
|
|
131
152
|
grid-column: 1 / -1;
|
|
132
153
|
}
|
|
133
154
|
|
|
155
|
+
/* Step rows + their readouts use the mono family — a technical step trace
|
|
156
|
+
(generate:/validate:/…) reads better fixed-width, matching the reference.
|
|
157
|
+
The iteration header ([data-reasoning-iter-n]) keeps the UI sans font. */
|
|
158
|
+
[data-reasoning-body] timeline-item-ui {
|
|
159
|
+
font-family: var(--a-font-family-code);
|
|
160
|
+
}
|
|
161
|
+
|
|
134
162
|
/* ═══════ Thought — horizontal dash in marker column, text in content ═══════ */
|
|
135
163
|
|
|
164
|
+
/* Thoughts are free-form annotations beside the spine — text in the content
|
|
165
|
+
column, no marker dot/dash (the continuous spine passes behind them). */
|
|
136
166
|
[data-reasoning-thought] {
|
|
137
167
|
display: grid;
|
|
138
168
|
grid-template-columns: subgrid;
|
|
139
169
|
align-items: center;
|
|
140
170
|
line-height: 1.5;
|
|
141
|
-
color: var(--agent-reasoning-fg, var(--agent-reasoning-fg-default));
|
|
171
|
+
color: var(--agent-reasoning-fg-muted, var(--agent-reasoning-fg-muted-default));
|
|
142
172
|
animation: _ar-fade var(--agent-reasoning-duration, var(--agent-reasoning-duration-default)) var(--agent-reasoning-easing, var(--agent-reasoning-easing-default));
|
|
143
173
|
}
|
|
144
174
|
|
|
145
|
-
[data-reasoning-thought]::before {
|
|
146
|
-
content: '';
|
|
147
|
-
grid-column: marker;
|
|
148
|
-
height: 1px;
|
|
149
|
-
background: var(--agent-reasoning-border, var(--agent-reasoning-border-default));
|
|
150
|
-
align-self: center;
|
|
151
|
-
width: 100%;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
175
|
[data-reasoning-thought] > [data-reasoning-thought-text] {
|
|
155
176
|
grid-column: content / -1;
|
|
156
177
|
min-width: 0;
|
|
@@ -159,15 +180,15 @@
|
|
|
159
180
|
|
|
160
181
|
/* ═══════ Plan — card in content+aside, marker empty ═══════ */
|
|
161
182
|
|
|
183
|
+
/* Plan reads as a flat up-front checklist in the content column — no bordered
|
|
184
|
+
box (that competed with the now-flattened iteration sections, the original
|
|
185
|
+
bug-03 "inconsistent card hierarchy" complaint). The PLAN label + ordered
|
|
186
|
+
list carry the distinction; the spine passes down its left. */
|
|
162
187
|
[data-reasoning-plan] {
|
|
163
188
|
grid-column: content / -1;
|
|
164
189
|
display: flex;
|
|
165
190
|
flex-direction: column;
|
|
166
191
|
gap: var(--a-space-1);
|
|
167
|
-
padding: var(--a-space-2) var(--a-space-3);
|
|
168
|
-
border: 1px solid var(--agent-reasoning-border, var(--agent-reasoning-border-default));
|
|
169
|
-
border-radius: var(--agent-reasoning-radius, var(--agent-reasoning-radius-default));
|
|
170
|
-
background: var(--agent-reasoning-iter-bg, var(--agent-reasoning-iter-bg-default));
|
|
171
192
|
}
|
|
172
193
|
|
|
173
194
|
[data-reasoning-plan-label] {
|
|
@@ -191,6 +212,10 @@
|
|
|
191
212
|
|
|
192
213
|
/* ═══════ Iteration — card with its own grid ═══════ */
|
|
193
214
|
|
|
215
|
+
/* Iterations read as continuous timeline sections (a status-icon header row
|
|
216
|
+
+ its nested steps tied by the timeline connector), NOT as bordered cards
|
|
217
|
+
that compete with the PLAN block. Flattened: no border / no fill / no box
|
|
218
|
+
padding — just the grid + row rhythm. (bug-03) */
|
|
194
219
|
[data-reasoning-iteration] {
|
|
195
220
|
display: grid;
|
|
196
221
|
grid-template-columns:
|
|
@@ -199,14 +224,6 @@
|
|
|
199
224
|
[aside] auto;
|
|
200
225
|
column-gap: var(--agent-reasoning-gap-col, var(--agent-reasoning-gap-col-default));
|
|
201
226
|
row-gap: var(--a-space-2);
|
|
202
|
-
padding: var(--agent-reasoning-iter-padding, var(--agent-reasoning-iter-padding-default));
|
|
203
|
-
border: 1px solid var(--agent-reasoning-iter-border, var(--agent-reasoning-iter-border-default));
|
|
204
|
-
border-radius: var(--agent-reasoning-radius, var(--agent-reasoning-radius-default));
|
|
205
|
-
background: var(--agent-reasoning-iter-bg, var(--agent-reasoning-iter-bg-default));
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
[data-reasoning-iteration][data-active] {
|
|
209
|
-
background: var(--agent-reasoning-iter-bg-active, var(--agent-reasoning-iter-bg-active-default));
|
|
210
227
|
}
|
|
211
228
|
|
|
212
229
|
[data-reasoning-iter-header] {
|
|
@@ -282,3 +299,13 @@
|
|
|
282
299
|
[data-reasoning-spinner] { animation: none; }
|
|
283
300
|
}
|
|
284
301
|
}
|
|
302
|
+
|
|
303
|
+
/* ═══════ Suppress timeline's own per-row connector inside agent-reasoning ═══════
|
|
304
|
+
The continuous body spine (see [data-reasoning-body][data-spine]::before)
|
|
305
|
+
owns the connector here; timeline-item's own ::after would double-draw and
|
|
306
|
+
fragment at every block boundary (each timeline-ui block stamps data-last on
|
|
307
|
+
its own last item, dropping that segment mid-run). This lives OUTSIDE @scope
|
|
308
|
+
and carries [data-step-id] (stamped on every step by #makeStepItem) to clear
|
|
309
|
+
timeline.css's :scope::after specificity ([0,1,1] → this is [0,1,3]). The
|
|
310
|
+
step dots (::before) are untouched. */
|
|
311
|
+
agent-reasoning-ui timeline-item-ui[data-step-id]::after { display: none; }
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
--agent-trace-detail-label-col-default: 9rem;
|
|
28
28
|
|
|
29
29
|
/* ── Motion ── */
|
|
30
|
-
--agent-trace-
|
|
30
|
+
--agent-trace-caret-dur-default: var(--a-duration-fast);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
:scope {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
border-radius: var(--a-radius-sm);
|
|
51
51
|
padding: var(--a-space-0-5) var(--a-space-1);
|
|
52
52
|
margin: calc(var(--a-space-0-5) * -1) calc(var(--a-space-1) * -1);
|
|
53
|
-
transition: background var(--agent-trace-
|
|
53
|
+
transition: background var(--agent-trace-caret-dur, var(--agent-trace-caret-dur-default));
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
[data-trace-root] > summary:hover {
|
|
@@ -94,12 +94,12 @@
|
|
|
94
94
|
margin-inline: 2px;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
[data-trace-
|
|
97
|
+
[data-trace-caret] {
|
|
98
98
|
flex-shrink: 0;
|
|
99
|
-
transition: transform var(--agent-trace-
|
|
99
|
+
transition: transform var(--agent-trace-caret-dur, var(--agent-trace-caret-dur-default));
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
[data-trace-root][open] [data-trace-
|
|
102
|
+
[data-trace-root][open] [data-trace-caret] {
|
|
103
103
|
transform: rotate(90deg);
|
|
104
104
|
}
|
|
105
105
|
|
|
@@ -225,20 +225,20 @@
|
|
|
225
225
|
text-align: end;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
/*
|
|
229
|
-
[data-trace-row-
|
|
228
|
+
/* Caret in the trailing column */
|
|
229
|
+
[data-trace-row-caret] {
|
|
230
230
|
--a-icon-size: 0.875em;
|
|
231
231
|
justify-self: end;
|
|
232
232
|
align-self: center;
|
|
233
|
-
transition: transform var(--a-duration-fast) var(--agent-trace-
|
|
233
|
+
transition: transform var(--a-duration-fast) var(--agent-trace-caret-dur, var(--a-duration-fast));
|
|
234
234
|
color: var(--agent-trace-fg-muted, var(--agent-trace-fg-muted-default));
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
details[data-trace-row][open] > summary > [data-trace-row-
|
|
237
|
+
details[data-trace-row][open] > summary > [data-trace-row-caret] {
|
|
238
238
|
transform: rotate(90deg);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
[data-trace-row-
|
|
241
|
+
[data-trace-row-caret-spacer] {
|
|
242
242
|
width: 0.875em;
|
|
243
243
|
justify-self: end;
|
|
244
244
|
}
|
|
@@ -128,7 +128,7 @@ class UIAgentTrace extends UIElement {
|
|
|
128
128
|
this.#rootEl.innerHTML = `
|
|
129
129
|
<summary>
|
|
130
130
|
<span data-trace-status>${pillsHTML}</span>
|
|
131
|
-
<icon-ui name="caret-right" color="muted" size="sm" data-trace-
|
|
131
|
+
<icon-ui name="caret-right" color="muted" size="sm" data-trace-caret></icon-ui>
|
|
132
132
|
</summary>
|
|
133
133
|
<div data-trace-body>
|
|
134
134
|
${this.#metrics.length ? `<div data-trace-rows${hasAnyDetails ? ' data-has-details' : ''}>${headerRow}${rowsHTML}</div>` : ''}
|
|
@@ -156,8 +156,8 @@ class UIAgentTrace extends UIElement {
|
|
|
156
156
|
<span data-trace-aux>${aux}</span>
|
|
157
157
|
${hasAnyDetails
|
|
158
158
|
? (hasDetails
|
|
159
|
-
? '<icon-ui name="caret-right" color="muted" data-trace-row-
|
|
160
|
-
: '<span data-trace-row-
|
|
159
|
+
? '<icon-ui name="caret-right" color="muted" data-trace-row-caret></icon-ui>'
|
|
160
|
+
: '<span data-trace-row-caret-spacer aria-hidden="true"></span>')
|
|
161
161
|
: ''}
|
|
162
162
|
`;
|
|
163
163
|
|
|
@@ -331,7 +331,14 @@ export class UIAlert extends UIElement {
|
|
|
331
331
|
|
|
332
332
|
#formatDueDate() {
|
|
333
333
|
if (!this.dueAt) return '';
|
|
334
|
-
|
|
334
|
+
// A date-only ISO string ("2026-05-20") parses as UTC midnight, which a
|
|
335
|
+
// behind-UTC locale then formats as the PREVIOUS calendar day. Consumers
|
|
336
|
+
// author these as plain calendar dates, so pin them to local midnight to
|
|
337
|
+
// preserve the authored day. Full timestamps (with time / offset) keep
|
|
338
|
+
// their exact instant.
|
|
339
|
+
const d = /^\d{4}-\d{2}-\d{2}$/.test(this.dueAt)
|
|
340
|
+
? new Date(`${this.dueAt}T00:00:00`)
|
|
341
|
+
: new Date(this.dueAt);
|
|
335
342
|
if (Number.isNaN(d.getTime())) return '';
|
|
336
343
|
try {
|
|
337
344
|
const lang = this.getAttribute('lang') || this.lang || undefined;
|
|
@@ -107,10 +107,18 @@
|
|
|
107
107
|
|
|
108
108
|
/* Trailing action area — optional single button or small button group.
|
|
109
109
|
flex-shrink:0 keeps it from collapsing; align-self:start anchors it
|
|
110
|
-
to the first text line under the `align-items:start` root.
|
|
110
|
+
to the first text line under the `align-items:start` root.
|
|
111
|
+
`order: 1` sorts it AFTER the content slot regardless of DOM order:
|
|
112
|
+
alert.js appends the auto-stamped [slot="content"] / [slot="leading"]
|
|
113
|
+
*after* any author-provided [slot="action"], so without an explicit
|
|
114
|
+
order the action button renders wedged between the icon and the
|
|
115
|
+
message instead of trailing. content's `flex: 1` then pushes the
|
|
116
|
+
action (+ close) to the right edge. Mirrors the dunning path, which
|
|
117
|
+
already assigns explicit per-slot order integers. */
|
|
111
118
|
:scope [slot="action"] {
|
|
112
119
|
flex-shrink: 0;
|
|
113
120
|
align-self: start;
|
|
121
|
+
order: 1;
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
/* Close button is a `<button-ui icon="x" variant="ghost" size="sm">`
|
|
@@ -123,6 +131,10 @@
|
|
|
123
131
|
rather than disconnected grey. */
|
|
124
132
|
:scope [slot="close"] {
|
|
125
133
|
flex-shrink: 0;
|
|
134
|
+
/* Sort last (after content order:0 and action order:1) so the dismiss
|
|
135
|
+
button is the right-most affordance. content's flex:1 pushes both
|
|
136
|
+
action + close to the trailing edge. */
|
|
137
|
+
order: 2;
|
|
126
138
|
min-height: calc(var(--alert-font, var(--alert-font-default)) * var(--alert-line-height, var(--alert-line-height-default)));
|
|
127
139
|
--button-fg-ghost: var(--alert-fg, var(--alert-fg-default));
|
|
128
140
|
--button-fg-ghost-hover: var(--alert-icon-fg, var(--alert-icon-fg-default));
|
|
@@ -21,14 +21,6 @@
|
|
|
21
21
|
"type": "string",
|
|
22
22
|
"default": ""
|
|
23
23
|
},
|
|
24
|
-
"name": {
|
|
25
|
-
"description": "Deprecated alias for `text` (logs a one-shot console warning; will be removed in a future release). New code should use `text=` instead.",
|
|
26
|
-
"type": "string",
|
|
27
|
-
"default": "",
|
|
28
|
-
"deprecated": true,
|
|
29
|
-
"deprecated_reason": "Use `text` instead. Will be removed in v0.6.0.",
|
|
30
|
-
"deprecated_since": "0.4.x"
|
|
31
|
-
},
|
|
32
24
|
"shape": {
|
|
33
25
|
"description": "Avatar shape",
|
|
34
26
|
"type": "string",
|
|
@@ -39,18 +31,14 @@
|
|
|
39
31
|
"default": "circle"
|
|
40
32
|
},
|
|
41
33
|
"size": {
|
|
42
|
-
"description": "Avatar size
|
|
34
|
+
"description": "Avatar size — canonical scale.",
|
|
43
35
|
"type": "string",
|
|
44
36
|
"enum": [
|
|
45
37
|
"xs",
|
|
46
38
|
"sm",
|
|
47
39
|
"md",
|
|
48
40
|
"lg",
|
|
49
|
-
"xl"
|
|
50
|
-
"small",
|
|
51
|
-
"medium",
|
|
52
|
-
"large",
|
|
53
|
-
"xlarge"
|
|
41
|
+
"xl"
|
|
54
42
|
],
|
|
55
43
|
"default": "md"
|
|
56
44
|
},
|