@adia-ai/web-components 0.7.21 → 0.7.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog — @adia-ai/web-components
2
2
 
3
+ ## [0.7.23] — 2026-06-30
4
+
5
+ ### Fixed
6
+ - **`button-ui` (`components/button/`) — child text now labels the button, same as `text=`.** A label written as child text (`<button-ui>Save</button-ui>`, no `text=` attr) was treated as icon-only and collapsed to a square icon slot with the text clipped — the collapse rule keyed off `:scope:not([text]), :scope[text=""]`, which can't see text-node children. `render()` now scans child nodes for non-whitespace text and reflects a JS-derived `[data-icon-only]` state **only** when there is neither a `text=` value nor child text; `button.css` keys its collapse + inline-level rules off `[data-icon-only]` instead of the `[text]` selectors. A child-text button now renders at full content width, identical to `text="Save"`, while a genuine `<button-ui icon="…">` still collapses; the icon-only accessible-name warning is re-gated to respect child text. Adds an `icon-only` state to `button.yaml`; `button.a2ui.json` + `dist/web-components.min.{js,css}` + `.sheet.js` (and the `theme-provider` / `everything` bundles) regenerated. (journal 2026-06-30 §1)
7
+
8
+ ### Changed
9
+ - **`accordion-ui` (`components/accordion/`) — normal block-flow gap, borderless items.** `--accordion-gap` changed from `0` to `var(--a-gap)`, so stacked items separate with the same canonical block-flow stack gap `col-ui` / `row-ui` / `grid-ui` use instead of butting together. The per-item `border-bottom` separator — with its `--accordion-item-border` token and the `:last-child` border reset — was removed for a clean borderless stack. Visible re-spacing, no public-API change (PATCH). (journal 2026-06-30 §2)
10
+
11
+ ## [0.7.22] — 2026-06-16
12
+
13
+ ### Changed
14
+ - **Surface tokens aligned onto the symmetric canvas ramp.** The `--a-canvas-*` surface assignments were consolidated onto one symmetric luminance ramp so elevation reads identically in light + dark (the prior mix of the flipping + symmetric ramps inverted in light mode). Chrome overlays — `components/modal`, `components/popover`, `components/drawer` — sit at `--a-canvas-dimmer`; `components/card` (`card-ui`) roots at `--a-canvas-base` with nesting `base → bright → brighter → brightest` (capped). `styles/colors/surfaces.css` gained the named canvas luminance scales (`--a-canvas-{dimmest…brightest}`); `styles/colors/parameters.css` updated; `drawer-ui` pulled on-ramp (was the only off-ramp overlay). `dist/` bundles (`host`, `theme-provider`, `web-components`) regenerated. Re-skins every modal/card/drawer/popover — a visible behavior change with no public-API change (PATCH). (journal 2026-06-15 §6)
15
+
3
16
  ## [0.7.21] — 2026-06-10
4
17
 
5
18
  ### Maintenance In-repo only: 57 `components/`/`traits/` `*.examples.html` files were de-annotated as part of the corpus curation (demo markers kept for the `?chunks` overlay) — `.examples.html` files are excluded from the published tarball (`files:` negation), so the npm artifact is unchanged.
@@ -9,7 +9,11 @@
9
9
  /* ── Container ── */
10
10
  @scope (accordion-ui) {
11
11
  :where(:scope) {
12
- --accordion-gap: 0;
12
+ /* Normal block-flow gap between items — the same ambient stack gap
13
+ col-ui/row-ui/grid-ui read (`--a-gap`, base `--a-gap-md`). Items now
14
+ separate by this gap rather than by flush hairline dividers, so the
15
+ item @scope below carries no inter-item border. */
16
+ --accordion-gap: var(--a-gap);
13
17
  }
14
18
 
15
19
  :scope {
@@ -24,7 +28,6 @@
24
28
  @scope (accordion-item-ui) {
25
29
  :where(:scope) {
26
30
  /* ── Colors ── */
27
- --accordion-item-border: var(--a-border-subtle);
28
31
  --accordion-item-header-fg: var(--a-fg-subtle);
29
32
  --accordion-item-header-fg-hover: var(--a-fg-strong);
30
33
  --accordion-item-header-bg-hover: var(--a-bg-muted);
@@ -53,11 +56,6 @@
53
56
  :scope {
54
57
  box-sizing: border-box;
55
58
  display: block;
56
- border-bottom: 1px solid var(--accordion-item-border);
57
- }
58
-
59
- :scope:last-child {
60
- border-bottom: none;
61
59
  }
62
60
 
63
61
  /* ── Header ── */
@@ -145,6 +145,11 @@
145
145
  "description": "Default, ready for interaction.",
146
146
  "name": "idle"
147
147
  },
148
+ {
149
+ "description": "No text label — neither the `text` attr nor non-whitespace child text. Reflected by render() as `[data-icon-only]`; the CSS collapses the button to a square icon slot (zero inline padding, width = height) and keeps it inline-level. A button labeled by child text (`<button-ui>Save</button-ui>`) is NOT icon-only and renders at full content width, same as `text=`.",
150
+ "attribute": "data-icon-only",
151
+ "name": "icon-only"
152
+ },
148
153
  {
149
154
  "description": "Non-interactive; dimmed.",
150
155
  "attribute": "disabled",
@@ -82,6 +82,24 @@ export class UIButton extends UIElement {
82
82
  }
83
83
  }
84
84
 
85
+ // A button is "labeled" by EITHER the [text] attribute (rendered via the
86
+ // ::after in button.css) OR direct light-DOM child text — `<button-ui>Save
87
+ // </button-ui>`, which renders as-is in the flex row. Both are valid labels;
88
+ // only a button with NEITHER is a square icon-only (or empty) button. Detect
89
+ // child text by scanning direct text nodes — the auto-stamped <icon-ui>
90
+ // children are element nodes (nodeType 1), so they're correctly ignored.
91
+ // Reflect the result as [data-icon-only]: button.css keys its collapse +
92
+ // inline-level rules off it (mirrors the derived-marker pattern in
93
+ // page.class.js's [data-header-stuck]). Child-text edits don't re-trigger
94
+ // render() (textContent isn't reactive — see the static-properties note
95
+ // above), but light-DOM children are parsed before the first render, so the
96
+ // initial classification is correct; toolbar spillover toggles the [text]
97
+ // attr (reactive), which re-runs this and keeps the marker in sync.
98
+ const hasChildText = Array.from(this.childNodes).some(
99
+ (n) => n.nodeType === 3 && n.textContent.trim() !== '',
100
+ );
101
+ this.toggleAttribute('data-icon-only', !this.text && !hasChildText);
102
+
85
103
  // FEEDBACK-15: warn when text= begins with a symbol that icon= already
86
104
  // renders (e.g. text="+ New Claim" icon="plus" → a doubled "+"). One-shot
87
105
  // per element via WeakSet; warning-only — the button still renders. The
@@ -113,7 +131,9 @@ export class UIButton extends UIElement {
113
131
  // so the bug class is diagnosable in dev without firing every
114
132
  // render tick. The warning is suppressed via a one-shot
115
133
  // WeakSet so subsequent re-renders stay quiet.
116
- if (this.icon && !this.text) {
134
+ if (this.icon && !this.text && !hasChildText) {
135
+ // (child text is itself the accessible name natively, so a button with
136
+ // light-DOM text is NOT icon-only and never warns here.)
117
137
  const ariaLabel = this.getAttribute('aria-label');
118
138
  const ariaLabelledBy = this.getAttribute('aria-labelledby');
119
139
  const titleAttr = this.getAttribute('title');
@@ -148,10 +148,11 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
148
148
  }
149
149
 
150
150
  /* Display convention (ADR-0037): block-level by default — a text button used
151
- directly in block flow fills its container. Icon-only buttons (no [text])
152
- stay inline-level, and [inline] forces inline for any button. Inside
153
- row-ui/col-ui/grid-ui this is moot (flex/grid items are blockified). */
154
- :scope:not([text]) { display: inline-flex; }
151
+ directly in block flow fills its container. Icon-only buttons (no text
152
+ label — see [data-icon-only] below) stay inline-level, and [inline] forces
153
+ inline for any button. Inside row-ui/col-ui/grid-ui this is moot (flex/grid
154
+ items are blockified). */
155
+ :scope[data-icon-only] { display: inline-flex; }
155
156
  :scope[inline] { display: inline-flex; }
156
157
 
157
158
  /* Trailing icon slot — for forward-affordance carets ("Next →"), distinct
@@ -284,8 +285,13 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
284
285
  cursor: not-allowed;
285
286
  }
286
287
 
287
- /* Icon-only (no text) */
288
- :scope:not([text]), :scope[text=""] {
288
+ /* Icon-only / empty — no text label from EITHER the [text] attr or direct
289
+ child text. The JS render() reflects [data-icon-only] (set only when
290
+ !text AND no non-whitespace child text), which subsumes the old
291
+ :not([text]) / [text=""] selectors AND correctly treats
292
+ `<button-ui>Save</button-ui>` as a labeled (full-width) button rather than
293
+ collapsing it into a square. */
294
+ :scope[data-icon-only] {
289
295
  --button-px: 0;
290
296
  width: var(--button-height);
291
297
  }
@@ -112,6 +112,14 @@ slots:
112
112
  states:
113
113
  - name: idle
114
114
  description: Default, ready for interaction.
115
+ - name: icon-only
116
+ description: >-
117
+ No text label — neither the `text` attr nor non-whitespace child text.
118
+ Reflected by render() as `[data-icon-only]`; the CSS collapses the button
119
+ to a square icon slot (zero inline padding, width = height) and keeps it
120
+ inline-level. A button labeled by child text (`<button-ui>Save</button-ui>`)
121
+ is NOT icon-only and renders at full content width, same as `text=`.
122
+ attribute: data-icon-only
115
123
  - name: disabled
116
124
  description: Non-interactive; dimmed.
117
125
  attribute: disabled
@@ -20,7 +20,7 @@
20
20
  --card-description-size: var(--a-caption-size);
21
21
 
22
22
  /* ── Colors ── */
23
- --card-bg: var(--a-canvas-1);
23
+ --card-bg: var(--a-canvas-base);
24
24
  --card-bg-padded: var(--a-canvas-0-scrim);
25
25
  --card-fg: var(--a-fg);
26
26
  --card-heading-fg: var(--a-fg-strong);
@@ -457,13 +457,14 @@
457
457
  }
458
458
 
459
459
  /* ═══════ Nested surface layering ═══════
460
- Step background up one canvas level per nesting depth.
460
+ Step background up the symmetric luminance ramp (base → bright → brighter →
461
+ brightest) per nesting depth; depths past brightest cap at brightest.
461
462
  :scope card-ui has specificity (0,1,1) which beats the
462
463
  :where(:scope) initializer (0,0,0) in each inner scope. */
463
- :scope card-ui { --card-bg: var(--a-canvas-1); --card-border: 1px solid var(--a-border); --a-radius: var(--a-radius-md); }
464
- :scope card-ui card-ui { --card-bg: var(--a-canvas-2); --a-radius: var(--a-radius-sm); }
465
- :scope card-ui card-ui card-ui { --card-bg: var(--a-canvas-3); }
466
- :scope card-ui card-ui card-ui card-ui { --card-bg: var(--a-canvas-4); }
467
- :scope card-ui card-ui card-ui card-ui card-ui { --card-bg: var(--a-canvas-5); }
468
- :scope card-ui card-ui card-ui card-ui card-ui card-ui { --card-bg: var(--a-canvas-6); }
464
+ :scope card-ui { --card-bg: var(--a-canvas-base); --card-border: 1px solid var(--a-border); --a-radius: var(--a-radius-md); }
465
+ :scope card-ui card-ui { --card-bg: var(--a-canvas-bright); --a-radius: var(--a-radius-sm); }
466
+ :scope card-ui card-ui card-ui { --card-bg: var(--a-canvas-brighter); }
467
+ :scope card-ui card-ui card-ui card-ui { --card-bg: var(--a-canvas-brightest); }
468
+ :scope card-ui card-ui card-ui card-ui card-ui { --card-bg: var(--a-canvas-brightest); }
469
+ :scope card-ui card-ui card-ui card-ui card-ui card-ui { --card-bg: var(--a-canvas-brightest); }
469
470
  }
@@ -30,7 +30,7 @@
30
30
  --drawer-easing: var(--a-easing-out);
31
31
 
32
32
  /* ── Colors ── */
33
- --drawer-bg: var(--a-canvas-1);
33
+ --drawer-bg: var(--a-canvas-dimmer);
34
34
  --drawer-border: var(--a-border-subtle);
35
35
  --drawer-divider: var(--a-border-subtle);
36
36
  --drawer-shadow: var(--a-shadow-lg);
@@ -11,7 +11,7 @@
11
11
  :where(:scope) {
12
12
  --modal-width: 32rem;
13
13
  --modal-radius: var(--a-radius-lg);
14
- --modal-bg: var(--a-bg-subtle);
14
+ --modal-bg: var(--a-canvas-dimmer);
15
15
  --modal-border: var(--a-border-subtle);
16
16
  --modal-shadow: var(--a-shadow-lg);
17
17
  --modal-backdrop: var(--a-scrim-dialog);
@@ -7,7 +7,7 @@
7
7
 
8
8
  /* ── Colors (default panel chrome — opt out per `:has(>card-ui)` rule
9
9
  below or by setting tokens to transparent / 0) ── */
10
- --popover-bg: var(--a-bg-subtle);
10
+ --popover-bg: var(--a-canvas-dimmer);
11
11
  --popover-border: var(--a-border-subtle);
12
12
  --popover-shadow: var(--a-shadow-lg);
13
13
  }