@adia-ai/web-components 0.8.23 → 0.8.24

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/components/agent-questions/agent-questions.yaml +0 -2
  3. package/components/alert/alert.class.js +5 -0
  4. package/components/alert/alert.yaml +2 -0
  5. package/components/calendar-grid/calendar-grid.yaml +3 -0
  6. package/components/card/card.css +12 -0
  7. package/components/combobox/combobox.class.js +1 -1
  8. package/components/combobox/combobox.yaml +0 -1
  9. package/components/date-range-picker/date-range-picker.class.js +1 -1
  10. package/components/date-range-picker/date-range-picker.yaml +0 -1
  11. package/components/datetime-picker/datetime-picker.class.js +1 -1
  12. package/components/datetime-picker/datetime-picker.yaml +0 -1
  13. package/components/drawer/drawer.class.js +5 -0
  14. package/components/drawer/drawer.yaml +2 -0
  15. package/components/feed/feed.class.js +5 -0
  16. package/components/feed/feed.yaml +2 -0
  17. package/components/input/input.class.js +5 -0
  18. package/components/input/input.yaml +3 -0
  19. package/components/list/list.css +13 -4
  20. package/components/modal/modal.class.js +5 -0
  21. package/components/modal/modal.yaml +2 -0
  22. package/components/nav-group/nav-group.class.js +5 -0
  23. package/components/nav-group/nav-group.yaml +2 -0
  24. package/components/pagination/pagination.yaml +3 -0
  25. package/components/select/select.class.js +2 -2
  26. package/components/select/select.yaml +0 -1
  27. package/components/swiper/swiper.class.js +5 -0
  28. package/components/swiper/swiper.yaml +3 -0
  29. package/components/toolbar/toolbar.class.js +20 -0
  30. package/components/toolbar/toolbar.yaml +2 -0
  31. package/dist/theme-provider.min.js +1 -1
  32. package/dist/web-components.min.css +1 -1
  33. package/dist/web-components.min.js +62 -62
  34. package/dist/web-components.sheet.js +1 -1
  35. package/package.json +1 -1
  36. package/patterns/admin-keys-and-export/admin-keys-and-export.examples.html +3 -3
  37. package/patterns/changelog-feed/changelog-feed.examples.html +3 -3
  38. package/patterns/comments-and-collaboration/comments-and-collaboration.examples.html +4 -4
  39. package/patterns/data-tables-inline-edit-and-tree/data-tables-inline-edit-and-tree.examples.html +2 -2
  40. package/patterns/marketing-engagement/marketing-engagement.examples.html +8 -8
  41. package/patterns/notifications-bell-and-digest/notifications-bell-and-digest.examples.html +1 -1
  42. package/patterns/profile-public-and-verification/profile-public-and-verification.examples.html +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog — @adia-ai/web-components
2
2
 
3
+ ## [0.8.24] — 2026-07-30
4
+
5
+ ### Fixed
6
+ - **`list-item-ui` two-line items center the leading glyph on the whole item** (gh#558, operator screenshot). The icon was pinned to the title row, hanging 9–18px above the item center on title+description rows — Material's two-line convention centers it. Explicit `grid-row: 1 / span 2` scoped by `:has([slot="description"])` (with no `grid-template-rows` the explicit grid has zero rows, so the old `1 / -1` collapsed to one row — the reason the earlier anatomy comment called them "identical"); single-line items untouched (probe: two-line offset 0/0/0, single-line 24px rows unchanged).
7
+ - **`card-ui` pins a direct `<footer>` to the card bottom** (gh#559, operator screenshot). In an equal-height grid row, a shorter card's CTA floated at content end (Free tier 42px above the edge vs 17px on its siblings) — the buttons were already in footers; the card just had no pinning rule. `:has(> footer)` promotes the card to a flex column with `margin-top: auto` on the footer; footerless cards keep block flow. Probe: 17/17/17.
8
+ - **`requiredIcons` drift cleared across 16 components** (gh#550). Eight primitives that auto-stamp icons (alert/drawer/feed/modal `x`, input steppers `caret-up`/`caret-down`, nav-group `caret-right`, swiper `caret-left`/`caret-right`, toolbar overflow `dots-three`) now declare `static requiredIcons`, mirrored in their yaml SoTs (calendar-grid and pagination gained the missing yaml blocks); four stale declarations pruned (combobox `check`, date-range-picker `arrow-right`, datetime-picker `clock`, select `magnifying-glass` — none ever stamped) and agent-questions' leftover yaml block removed (options render via option-card-ui since gh#276). Checker itself hardened: `//` line comments no longer read as stamp sites (button `plus` false positive) and yaml list entries may carry trailing `#` comments (select's three phantom mismatches). 125/125 components clean.
9
+ - **`toolbar-ui` overflow measurement traps closed** (gh#528). (1) Flex-grow children (spacers, stretched groups) measured at their EXPANDED width, so the row always read "full" and the last action spilled unrecoverably — grow is zeroed for the read and restored. (2) A `display:none` mount committed a spill from a 0-width reading and stranded the bar collapsed — a zero-width guard now leaves everything visible until the ResizeObserver delivers a real size. Browser-verified both ways.
10
+ - **Corpus/demo enum drift swept** (gh#529): 41 uses of never-implemented values (Tag `muted`/`primary`, Text `primary`/`muted`/`xxl`, Card `soft`/`primary`, Badge `subtle`, Chart `muted`, Button `danger`) mapped to their nearest real values across 15 harvest sources — they silently rendered as defaults. `verify:corpus` warnings 138 → 97.
11
+ - **10 standalone example routes actually render** (gh#530): the sitemap pointed iframe-served routes at headless `.contents.html` fragments; thin standalone wrappers added (single-source fetch-inject), annotations repointed, `frame`/`theme-provider` demos wired for phosphor. 108/108 clean. The `check-required-icons` checker also now reads `<comp>.class.js` and all stamp shapes — 20 false positives gone, 19 real findings exposed → gh#550.
12
+
13
+ ### Maintenance
14
+ - **`dist/` bundles rebuilt** in this cut's window (4 file(s)) — regenerated from the source changes described above, not independent edits.
15
+ - **`patterns/` touched in this release window** (7 file(s), e.g. `admin-keys-and-export/admin-keys-and-export.examples.html`) — carried by the entries above.
16
+
3
17
  ## [0.8.23] — 2026-07-30
4
18
 
5
19
  ### Removed
@@ -56,8 +56,6 @@ states:
56
56
  description: Default, ready for interaction.
57
57
  traits: []
58
58
  tokens: {}
59
- requiredIcons:
60
- - check
61
59
  a2ui:
62
60
  rules:
63
61
  - rule: 'Multi-choice clarifying-question card emitted by an agent when it needs disambiguation before proceeding.'
@@ -42,6 +42,11 @@ function _warnOnce(key, message) {
42
42
  }
43
43
 
44
44
  export class UIAlert extends UIElement {
45
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
46
+ // Aggregated by installIconLoadersForRegistered() across all defined
47
+ // elements. Audited by check-required-icons.mjs.
48
+ static requiredIcons = ['x'];
49
+
45
50
  static properties = {
46
51
  text: { type: String, default: '', reflect: true },
47
52
  title: { type: String, default: '', reflect: true },
@@ -173,6 +173,8 @@ states:
173
173
  description: Default, ready for interaction.
174
174
  traits: []
175
175
  tokens: {}
176
+ requiredIcons:
177
+ - x
176
178
  a2ui:
177
179
  rules:
178
180
  - rule: 'Inline alert/banner for status messages within a content region. Severity via variant (info, success, warn, error).'
@@ -108,6 +108,9 @@ tokens:
108
108
  --calendar-grid-day-today-color:
109
109
  description: Accent color used for the today-indicator dot + numeral tint.
110
110
  default: var(--md-sys-color-primary)
111
+ requiredIcons:
112
+ - caret-left
113
+ - caret-right
111
114
  a2ui:
112
115
  rules:
113
116
  - >-
@@ -68,6 +68,18 @@
68
68
  flex: 1 1 auto;
69
69
  }
70
70
 
71
+ /* A card with a direct footer pins it to the bottom edge (gh#559):
72
+ in an equal-height grid/flex row, a shorter card's CTA otherwise
73
+ floats at content end while its siblings' sit lower. Scoped via
74
+ :has(> footer) so footerless cards keep plain block flow. */
75
+ :scope:has(> footer) {
76
+ display: flex;
77
+ flex-direction: column;
78
+ }
79
+ :scope > footer {
80
+ margin-top: auto;
81
+ }
82
+
71
83
  /* ═══════ Variants — token-only overrides ═══════ */
72
84
 
73
85
  /* `outline` is a documented alias for `outlined` (yaml). */
@@ -58,7 +58,7 @@ export class UICombobox extends UIFormElement {
58
58
  // base-class deprecation warning that targets inert above-field labels.
59
59
  static labelDeprecated = false;
60
60
 
61
- static requiredIcons = ['caret-down', 'x-circle', 'check'];
61
+ static requiredIcons = ['caret-down', 'x-circle'];
62
62
 
63
63
  static properties = {
64
64
  ...UIFormElement.properties,
@@ -257,7 +257,6 @@ tokens:
257
257
  requiredIcons:
258
258
  - caret-down
259
259
  - x-circle
260
- - check
261
260
  a2ui:
262
261
  rules:
263
262
  - >-
@@ -130,7 +130,7 @@ export class UIDateRangePicker extends UIFormElement {
130
130
  // §154: Phosphor icons this primitive auto-stamps (without consumer
131
131
  // markup). Aggregated by installIconLoadersForRegistered() across all
132
132
  // defined elements. Audited by check-required-icons.mjs.
133
- static requiredIcons = ['calendar', 'caret-down', 'arrow-right'];
133
+ static requiredIcons = ['calendar', 'caret-down'];
134
134
 
135
135
  static get properties() {
136
136
  return {
@@ -195,7 +195,6 @@ tokens:
195
195
  requiredIcons:
196
196
  - calendar
197
197
  - caret-down
198
- - arrow-right
199
198
  a2ui:
200
199
  rules:
201
200
  - rule: 'DateRangePicker.value MUST be `{from, to}` with both ISO 8601 dates, OR null. Either side null is invalid mid-state and the validator should reject it (use `input` event for partial state).'
@@ -122,7 +122,7 @@ export class UIDatetimePicker extends UIFormElement {
122
122
  // §154: Phosphor icons this primitive auto-stamps (without consumer
123
123
  // markup). Aggregated by installIconLoadersForRegistered() across all
124
124
  // defined elements. Audited by check-required-icons.mjs.
125
- static requiredIcons = ['calendar', 'clock', 'caret-down'];
125
+ static requiredIcons = ['calendar', 'caret-down'];
126
126
 
127
127
  static get properties() {
128
128
  return {
@@ -210,7 +210,6 @@ tokens:
210
210
  default: var(--a-easing)
211
211
  requiredIcons:
212
212
  - calendar
213
- - clock
214
213
  - caret-down
215
214
  a2ui:
216
215
  rules:
@@ -60,6 +60,11 @@ export class UIDrawer extends UIElement {
60
60
  // doesn't carry a stale reason. Per FEEDBACK-06 §2.
61
61
  #closeReason = 'programmatic';
62
62
 
63
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
64
+ // Aggregated by installIconLoadersForRegistered() across all defined
65
+ // elements. Audited by check-required-icons.mjs.
66
+ static requiredIcons = ['x'];
67
+
63
68
  static properties = {
64
69
  text: { type: String, default: '', reflect: true },
65
70
  side: { type: String, default: 'right', reflect: true },
@@ -131,6 +131,8 @@ states:
131
131
  description: Default, ready for interaction.
132
132
  traits: []
133
133
  tokens: {}
134
+ requiredIcons:
135
+ - x
134
136
  a2ui:
135
137
  rules:
136
138
  - >-
@@ -43,6 +43,11 @@ import { UIElement, html } from '../../core/element.js';
43
43
  /* ── Container — one per position, mounted into document.body ── */
44
44
 
45
45
  export class UIFeedContainer extends UIElement {
46
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
47
+ // Aggregated by installIconLoadersForRegistered() across all defined
48
+ // elements. Audited by check-required-icons.mjs.
49
+ static requiredIcons = ['x'];
50
+
46
51
  static properties = {
47
52
  position: { type: String, default: 'bottom-right', reflect: true },
48
53
  max: { type: Number, default: 5, reflect: true },
@@ -57,6 +57,8 @@ related:
57
57
  - Toast
58
58
  - Alert
59
59
 
60
+ requiredIcons:
61
+ - x
60
62
  a2ui:
61
63
  rules:
62
64
  - rule: 'Top-layer notification feed channel — singleton per position (top-right, bottom-center, etc.) mounted lazily into document.body.'
@@ -66,6 +66,11 @@ export class UIInput extends UIFormElement {
66
66
  // motivated the deprecation.
67
67
  static labelDeprecated = false;
68
68
 
69
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
70
+ // Aggregated by installIconLoadersForRegistered() across all defined
71
+ // elements. Audited by check-required-icons.mjs.
72
+ static requiredIcons = ['caret-up', 'caret-down'];
73
+
69
74
  static properties = {
70
75
  ...UIFormElement.properties,
71
76
  placeholder: { type: String, default: '', reflect: true },
@@ -238,6 +238,9 @@ tokens:
238
238
  description: Override border radius
239
239
  --input-transition:
240
240
  description: Override transition timing
241
+ requiredIcons:
242
+ - caret-up
243
+ - caret-down
241
244
  a2ui:
242
245
  rules:
243
246
  - >-
@@ -107,11 +107,11 @@
107
107
  }
108
108
 
109
109
  /* Anatomy (header-row model):
110
- row 1 = icon (col 1) · text/title (col 2) · action (col 3), all aligned
111
- on the title row. row 2 = description, spanning col 2 / -1 (under the
110
+ row 1 = text/title (col 2) · action (col 3), aligned on the title row.
111
+ icon (col 1) spans both rows, centered on the whole item (gh#558).
112
+ row 2 = description, spanning col 2 / -1 (under the
112
113
  action) so multi-line supporting text uses the full content width rather
113
- than being boxed into col 2 beside the action. For icon+text-only items
114
- there is a single row, so `grid-row: 1` is identical to the old `1 / -1`.
114
+ than being boxed into col 2 beside the action.
115
115
  `[slot="content"]` (used when consumer provides custom rendering)
116
116
  spans all columns. */
117
117
  :scope {
@@ -147,6 +147,15 @@
147
147
  /* carries the old column-gap (gh#524) */
148
148
  margin-inline-end: var(--list-item-gap-column);
149
149
  }
150
+ /* Two-line items center the glyph on the WHOLE item (gh#558) — Material's
151
+ two-line convention; pinned to row 1 it hung above the item center.
152
+ The span must be explicit (`span 2`): with no grid-template-rows the
153
+ explicit grid has zero rows, so `1 / -1` collapses back to one row.
154
+ Scoped by :has() so single-line items don't mint an empty second row
155
+ (which would charge row-gap below the content). */
156
+ :scope:has([slot="description"]) [slot="icon"] {
157
+ grid-row: 1 / span 2;
158
+ }
150
159
  /* An empty stamped icon span must not resurrect the ghost track. */
151
160
  :scope [slot="icon"]:empty {
152
161
  display: none;
@@ -51,6 +51,11 @@ export class UIModal extends UIElement {
51
51
  #closeTimer = null;
52
52
  #dialogRef = null;
53
53
 
54
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
55
+ // Aggregated by installIconLoadersForRegistered() across all defined
56
+ // elements. Audited by check-required-icons.mjs.
57
+ static requiredIcons = ['x'];
58
+
54
59
  static properties = {
55
60
  text: { type: String, default: '', reflect: true },
56
61
  size: { type: String, default: 'md', reflect: true },
@@ -79,6 +79,8 @@ tokens:
79
79
  description: Override surface border radius
80
80
  --modal-shadow:
81
81
  description: Override surface box shadow
82
+ requiredIcons:
83
+ - x
82
84
  a2ui:
83
85
  rules:
84
86
  - >-
@@ -30,6 +30,11 @@ import { anchorPopover } from '../../core/anchor.js';
30
30
  import { logicalSlotted } from '../../core/logical-children.js';
31
31
 
32
32
  export class UINavGroup extends UIElement {
33
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
34
+ // Aggregated by installIconLoadersForRegistered() across all defined
35
+ // elements. Audited by check-required-icons.mjs.
36
+ static requiredIcons = ['caret-right'];
37
+
33
38
  static properties = {
34
39
  text: { type: String, default: '', reflect: true },
35
40
  icon: { type: String, default: '', reflect: true },
@@ -81,6 +81,8 @@ states:
81
81
 
82
82
  traits: []
83
83
  tokens: {}
84
+ requiredIcons:
85
+ - caret-right
84
86
  a2ui:
85
87
  rules:
86
88
  - >-
@@ -64,6 +64,9 @@ states:
64
64
  description: Default, ready for interaction.
65
65
  traits: []
66
66
  tokens: {}
67
+ requiredIcons:
68
+ - caret-left
69
+ - caret-right
67
70
  a2ui:
68
71
  rules:
69
72
  - rule: 'Renders below tables, card grids, or list views for paginated data. Emits page-change events.'
@@ -26,8 +26,8 @@ export class UISelect extends UIFormElement {
26
26
  // across all defined elements. Audited by check-required-icons.mjs
27
27
  // (slot 11). Per FEEDBACK-06 §4 + FEEDBACK-07 §4.
28
28
  // SPEC-040: [multiple] mode stamps <tag-ui> chips (own `x`), checkbox
29
- // indicator (`check`), and search-input prefix (`magnifying-glass`).
30
- static requiredIcons = ['caret-down', 'check', 'x', 'magnifying-glass'];
29
+ // indicator (`check`).
30
+ static requiredIcons = ['caret-down', 'check', 'x'];
31
31
 
32
32
  // §225 (v0.5.9, FEEDBACK-10 §3): once-per-element console.warn dedup when
33
33
  // consumer authors children that aren't native <option>/<optgroup>. The
@@ -274,7 +274,6 @@ requiredIcons:
274
274
  - caret-down
275
275
  - check # checkbox indicator on each option in [multiple] mode
276
276
  - x # chip dismiss + clear-all affordance ([multiple] + [clearable])
277
- - magnifying-glass # search-input prefix ([searchable])
278
277
  a2ui:
279
278
  rules:
280
279
  - >-
@@ -37,6 +37,11 @@
37
37
  import { UIElement } from '../../core/element.js';
38
38
 
39
39
  export class UISwiper extends UIElement {
40
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
41
+ // Aggregated by installIconLoadersForRegistered() across all defined
42
+ // elements. Audited by check-required-icons.mjs.
43
+ static requiredIcons = ['caret-left', 'caret-right'];
44
+
40
45
  static properties = {
41
46
  autoplay: { type: Boolean, default: false, reflect: true },
42
47
  interval: { type: Number, default: 5000, reflect: true },
@@ -95,6 +95,9 @@ states:
95
95
  description: Default, ready for interaction.
96
96
  traits: []
97
97
  tokens: {}
98
+ requiredIcons:
99
+ - caret-left
100
+ - caret-right
98
101
  a2ui:
99
102
  rules:
100
103
  - rule: 'Horizontal slide carousel with touch + arrow nav. Hosts arbitrary children as slides.'
@@ -90,6 +90,11 @@ function outerWidth(el) {
90
90
  }
91
91
 
92
92
  export class UIToolbar extends UIElement {
93
+ // Phosphor icons this primitive auto-stamps (without consumer markup).
94
+ // Aggregated by installIconLoadersForRegistered() across all defined
95
+ // elements. Audited by check-required-icons.mjs.
96
+ static requiredIcons = ['dots-three'];
97
+
93
98
  static properties = {
94
99
  gap: { type: String, default: 'sm', reflect: true },
95
100
  align: { type: String, default: 'start', reflect: true },
@@ -320,6 +325,12 @@ export class UIToolbar extends UIElement {
320
325
  trigger.hidden = true;
321
326
 
322
327
  // 2. Measure.
328
+ // Hidden-ancestor guard (gh#528): a display:none mount reads
329
+ // clientWidth 0 — committing a spill from that reading strands the
330
+ // bar collapsed. Step 1 already restored everything visible, so
331
+ // leaving now is the correct state; the ResizeObserver fires again
332
+ // with a real size when the ancestor becomes visible.
333
+ if (this.clientWidth === 0) return;
323
334
  const style = getComputedStyle(this);
324
335
  const padL = parseFloat(style.paddingLeft) || 0;
325
336
  const padR = parseFloat(style.paddingRight) || 0;
@@ -329,7 +340,16 @@ export class UIToolbar extends UIElement {
329
340
  // Include horizontal margins — components like divider-ui add their own
330
341
  // margin-inline which getBoundingClientRect() does NOT include but flex
331
342
  // layout DOES count toward the row width.
343
+ // Grow-item guard (gh#528): a flex-grow child (a spacer, a stretched
344
+ // group) measures at its EXPANDED width — the row then always reads
345
+ // "full" and the last real action spills unrecoverably (the pattern
346
+ // bug gh#494's build hit). Measure grow items at their natural size
347
+ // by zeroing flex-grow for the read, then restoring.
348
+ const grown = all.filter(el => parseFloat(getComputedStyle(el).flexGrow) > 0);
349
+ const savedGrow = grown.map(el => el.style.flexGrow);
350
+ for (const el of grown) el.style.flexGrow = '0';
332
351
  const widths = all.map(el => outerWidth(el));
352
+ grown.forEach((el, i) => { el.style.flexGrow = savedGrow[i]; });
333
353
  const total = widths.reduce((a, w) => a + w, 0) + Math.max(0, all.length - 1) * gap;
334
354
 
335
355
  // Reserve OVERFLOW_BUFFER worth of headroom — start spilling sooner
@@ -41,6 +41,8 @@ states:
41
41
  description: Default, ready for interaction.
42
42
  traits: []
43
43
  tokens: {}
44
+ requiredIcons:
45
+ - dots-three
44
46
  a2ui:
45
47
  rules:
46
48
  - rule: 'Horizontal action bar — hosts <button-ui>, <toolbar-group-ui>, and <divider-ui> children.'