@adia-ai/web-components 0.8.34 → 0.8.35
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 +9 -0
- package/components/agent-questions/agent-questions.class.js +0 -1
- package/components/badge/badge.css +27 -3
- package/components/badge/badge.examples.md +4 -4
- package/components/card/card.css +44 -1
- package/components/check/check.a2ui.json +25 -11
- package/components/check/check.class.js +5 -0
- package/components/check/check.css +21 -0
- package/components/check/check.d.ts +2 -0
- package/components/check/check.examples.md +4 -4
- package/components/check/check.yaml +26 -7
- package/components/demo-toggle/demo-toggle.css +4 -0
- package/components/demo-toggle/demo-toggle.examples.md +4 -4
- package/components/feed/feed-item.a2ui.json +3 -2
- package/components/feed/feed-item.yaml +7 -1
- package/components/feed/feed.css +28 -5
- package/components/field/field.examples.md +4 -4
- package/components/image/image.class.js +8 -0
- package/components/nav-group/nav-group.css +12 -1
- package/components/option-card/option-card.a2ui.json +10 -10
- package/components/option-card/option-card.css +32 -16
- package/components/option-card/option-card.yaml +19 -15
- package/components/radio/radio.examples.md +4 -4
- package/components/range/range.css +8 -4
- package/components/slider/slider.a2ui.json +6 -3
- package/components/slider/slider.css +28 -12
- package/components/slider/slider.yaml +11 -3
- package/components/stat/stat.examples.md +4 -4
- package/components/swatch/swatch.css +14 -6
- package/components/switch/switch.examples.md +4 -4
- package/components/table-toolbar/table-toolbar.css +10 -1
- package/components/tabs/tabs.css +10 -4
- package/components/tag/tag.class.js +14 -1
- package/components/tag/tag.css +63 -5
- package/components/text/text.examples.md +4 -4
- package/components/timeline/timeline-item.a2ui.json +2 -2
- package/components/timeline/timeline-item.yaml +2 -2
- package/components/timeline/timeline.css +33 -5
- package/components/timeline/timeline.d.ts +2 -2
- package/components/toast/toast.css +28 -5
- package/custom-elements.json +469 -46
- package/dist/theme-provider.min.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +4 -4
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -1
- package/patterns/access-requests/access-requests.examples.html +3 -3
- package/patterns/admin-keys-and-export/admin-keys-and-export.examples.html +3 -3
- package/patterns/admin-shell/admin-shell.examples.html +3 -4
- package/patterns/agent-cost/agent-cost.examples.html +3 -3
- package/patterns/agent-memory/agent-memory.examples.html +3 -3
- package/patterns/agent-prompt-library/agent-prompt-library.examples.html +3 -3
- package/patterns/agent-tool-call/agent-tool-call.examples.html +3 -3
- package/patterns/alert-dialog/alert-dialog.examples.html +3 -3
- package/patterns/app-nav/app-nav.examples.html +4 -4
- package/patterns/approvals/approvals.examples.html +3 -3
- package/patterns/audit-log/audit-log.examples.html +3 -3
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.html +19 -9
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.js +2 -2
- package/patterns/changelog-feed/changelog-feed.examples.html +3 -3
- package/patterns/chart-in-card/chart-in-card.examples.html +37 -3
- package/patterns/chart-in-card/chart-in-card.examples.js +12 -0
- package/patterns/chart-in-card/chart-in-card.html +6 -0
- package/patterns/chat-shell/chat-shell.examples.html +3 -4
- package/patterns/comments-and-collaboration/comments-and-collaboration.examples.html +3 -3
- package/patterns/conversion-funnel/conversion-funnel.examples.html +3 -3
- package/patterns/data-tables-inline-edit-and-tree/data-tables-inline-edit-and-tree.examples.html +3 -3
- package/patterns/diff-review/diff-review.examples.html +3 -3
- package/patterns/editor-shell/editor-shell.examples.html +3 -4
- package/patterns/export-flow/export-flow.examples.html +3 -3
- package/patterns/filter-bar/filter-bar.examples.html +3 -3
- package/patterns/form-drawer/form-drawer.examples.html +3 -3
- package/patterns/forms-conditional-and-autocomplete/forms-conditional-and-autocomplete.examples.html +3 -3
- package/patterns/inline-dialog/inline-dialog.examples.html +3 -3
- package/patterns/kanban-board/kanban-board.examples.html +3 -3
- package/patterns/layout/layout.examples.html +4 -7
- package/patterns/marketing-engagement/marketing-engagement.examples.html +3 -3
- package/patterns/notifications-bell-and-digest/notifications-bell-and-digest.examples.html +3 -3
- package/patterns/permissions-matrix/permissions-matrix.examples.html +3 -3
- package/patterns/permissions-role-picker/permissions-role-picker.examples.html +3 -3
- package/patterns/permissions-sharing/permissions-sharing.examples.html +3 -3
- package/patterns/profile-public-and-verification/profile-public-and-verification.examples.html +3 -3
- package/patterns/record-detail-drawer/record-detail-drawer.examples.html +3 -3
- package/patterns/responsive-shell-sidebar/responsive-shell-sidebar.examples.html +3 -3
- package/patterns/retention-cohort/retention-cohort.examples.html +3 -3
- package/patterns/search-discovery/search-discovery.examples.html +3 -3
- package/patterns/system-banners/system-banners.examples.html +3 -3
- package/patterns/timezone-selector/timezone-selector.examples.html +3 -3
- package/patterns/wizard-drawer/wizard-drawer.examples.html +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
2
|
|
|
3
|
+
## [0.8.35] — 2026-08-13
|
|
4
|
+
|
|
5
|
+
### Maintenance
|
|
6
|
+
- **Source fixes this window are carried per-file below; the narrative CHANGELOG entries live with the substantive packages.** Bumped in lockstep per `scripts/release/check-lockstep.mjs`. Headline v0.8.35 work shipped in factory-DX program (scaffold boot+CSS fixes, class-B npm marketplace, consumer CI recipe, DX sweep) + audit-wave plugin hardening + ~20 component/pattern fixes. See `packages/plugins/adia-ui-factory/CHANGELOG.md#0835--2026-08-13` for details.
|
|
7
|
+
- **`components/` touched in this release window** (58 file(s), e.g. `agent-questions/agent-questions.class.js`) — carried by the entries above.
|
|
8
|
+
- **`dist/` bundles rebuilt** in this cut's window (4 file(s)) — regenerated from the source changes described above, not independent edits.
|
|
9
|
+
- **`patterns/` touched in this release window** (43 file(s), e.g. `access-requests/access-requests.examples.html`) — carried by the entries above.
|
|
10
|
+
- **`traits/` touched in this release window** (5 file(s), e.g. `anchor-positioning/anchor-positioning.examples.html`) — carried by the entries above.
|
|
11
|
+
|
|
3
12
|
## [0.8.34] — 2026-08-11
|
|
4
13
|
|
|
5
14
|
### Fixed
|
|
@@ -133,7 +133,6 @@ export class UIAgentQuestions extends UIElement {
|
|
|
133
133
|
this.#submitEl = document.createElement('button-ui');
|
|
134
134
|
this.#submitEl.setAttribute('text', this.submitLabel || 'Continue');
|
|
135
135
|
this.#submitEl.setAttribute('variant', 'primary');
|
|
136
|
-
this.#submitEl.setAttribute('size', 'sm');
|
|
137
136
|
this.#submitEl.setAttribute('disabled', '');
|
|
138
137
|
if (!this.multi) this.#submitEl.hidden = true;
|
|
139
138
|
this.#submitEl.addEventListener('press', this.#onSubmit);
|
|
@@ -20,8 +20,22 @@
|
|
|
20
20
|
only radius moved. */
|
|
21
21
|
--badge-radius: var(--a-radius-full);
|
|
22
22
|
--badge-px: var(--a-space-1-5);
|
|
23
|
-
|
|
23
|
+
/* gh#1084: block padding flattened toward 1px per tier — the
|
|
24
|
+
--badge-min-h floor (below) now owns the chip's vertical size, so
|
|
25
|
+
py no longer has to carry it. Was --a-space-0-5 (2px); mirrors the
|
|
26
|
+
identical tag-ui change (same rationale, tag.css). */
|
|
27
|
+
--badge-py: var(--a-space-px);
|
|
24
28
|
--badge-gap: var(--a-space-1);
|
|
29
|
+
/* gh#1084 — min-height floor, decoupled from padding (mirrors
|
|
30
|
+
tags-input-ui's --tags-input-min-h, and tag-ui's own --tag-min-h
|
|
31
|
+
added in the same change). Component-owned fixed rem constants
|
|
32
|
+
(not density-scaled) calibrated to badge's CURRENT rendered
|
|
33
|
+
height at each tier — measured 12/15/20px sm/md/lg before this
|
|
34
|
+
change — so this is a non-regressing addition: shrinking py
|
|
35
|
+
toward 1px no longer shrinks the badge, the floor holds the line. */
|
|
36
|
+
--badge-min-h: 0.9375rem; /* 15px @ d=1 — md */
|
|
37
|
+
--badge-min-h-sm: 0.75rem; /* 12px @ d=1 */
|
|
38
|
+
--badge-min-h-lg: 1.25rem; /* 20px @ d=1 */
|
|
25
39
|
/* One rung down the --a-ui-* scale (gh#965) — ladder shifts with it
|
|
26
40
|
(sm=2xs, lg=sm) so tiers stay one rung apart. Mirrors tag-ui. */
|
|
27
41
|
--badge-font-size: var(--a-ui-xs);
|
|
@@ -45,8 +59,11 @@
|
|
|
45
59
|
and tag share this md baseline and this exact reasoning). */
|
|
46
60
|
--badge-px-sm: var(--a-space-1);
|
|
47
61
|
--badge-px-lg: var(--a-space-2);
|
|
62
|
+
/* gh#1084: py flattened toward 1px/tier now that --badge-min-h
|
|
63
|
+
floors the box — was --a-space-px/--a-space-1 (1px/4px); mirrors
|
|
64
|
+
the identical tag-ui change (tag.css). */
|
|
48
65
|
--badge-py-sm: var(--a-space-px);
|
|
49
|
-
--badge-py-lg: var(--a-space-
|
|
66
|
+
--badge-py-lg: var(--a-space-0-5);
|
|
50
67
|
--badge-font-size-sm: var(--a-ui-2xs);
|
|
51
68
|
--badge-font-size-lg: var(--a-ui-sm);
|
|
52
69
|
text-align: start; /* §text-align-reset — blocks inheritance from centered ancestors */
|
|
@@ -60,6 +77,10 @@
|
|
|
60
77
|
justify-content: center;
|
|
61
78
|
gap: var(--badge-gap);
|
|
62
79
|
width: fit-content;
|
|
80
|
+
/* gh#1084: floor, not a fixed size — mirrors tags-input-ui's own
|
|
81
|
+
min-height and tag-ui's identical addition (tag.css). Decouples
|
|
82
|
+
the badge's vertical size from --badge-py. */
|
|
83
|
+
min-height: var(--badge-min-h);
|
|
63
84
|
padding: var(--badge-py) var(--badge-px);
|
|
64
85
|
background: var(--badge-bg);
|
|
65
86
|
color: var(--badge-fg);
|
|
@@ -239,15 +260,18 @@
|
|
|
239
260
|
--badge-px: var(--badge-px-sm);
|
|
240
261
|
--badge-py: var(--badge-py-sm);
|
|
241
262
|
--badge-font-size: var(--badge-font-size-sm);
|
|
263
|
+
--badge-min-h: var(--badge-min-h-sm);
|
|
242
264
|
}
|
|
243
265
|
:scope[size="md"] {
|
|
244
266
|
--badge-px: var(--a-space-1-5);
|
|
245
|
-
--badge-py: var(--a-space-
|
|
267
|
+
--badge-py: var(--a-space-px);
|
|
246
268
|
--badge-font-size: var(--a-ui-xs);
|
|
269
|
+
--badge-min-h: 0.9375rem; /* 15px @ d=1 — matches the :where(:scope) default */
|
|
247
270
|
}
|
|
248
271
|
:scope[size="lg"] {
|
|
249
272
|
--badge-px: var(--badge-px-lg);
|
|
250
273
|
--badge-py: var(--badge-py-lg);
|
|
251
274
|
--badge-font-size: var(--badge-font-size-lg);
|
|
275
|
+
--badge-min-h: var(--badge-min-h-lg);
|
|
252
276
|
}
|
|
253
277
|
}
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
```html
|
|
12
12
|
<row-ui gap="6" align="start" wrap>
|
|
13
13
|
<col-ui gap="2">
|
|
14
|
-
<text-ui variant="caption" color="muted">
|
|
15
|
-
<div
|
|
14
|
+
<text-ui variant="caption" color="muted">scale="ui-sm"</text-ui>
|
|
15
|
+
<div scale="ui-sm">
|
|
16
16
|
<row-ui gap="2">
|
|
17
17
|
<badge-ui text="New" variant="success"></badge-ui>
|
|
18
18
|
<badge-ui text="Beta" variant="info"></badge-ui>
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
</div>
|
|
32
32
|
</col-ui>
|
|
33
33
|
<col-ui gap="2">
|
|
34
|
-
<text-ui variant="caption" color="muted">
|
|
35
|
-
<div
|
|
34
|
+
<text-ui variant="caption" color="muted">scale="content-md"</text-ui>
|
|
35
|
+
<div scale="content-md">
|
|
36
36
|
<row-ui gap="2">
|
|
37
37
|
<badge-ui text="New" variant="success"></badge-ui>
|
|
38
38
|
<badge-ui text="Beta" variant="info"></badge-ui>
|
package/components/card/card.css
CHANGED
|
@@ -80,6 +80,18 @@
|
|
|
80
80
|
margin-top: auto;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/* Flex containers never collapse adjacent margins the way block flow
|
|
84
|
+
does (gh#1098) — once :has(> footer) above switches the card to
|
|
85
|
+
flex-column, a plain header followed by a plain section stacks BOTH
|
|
86
|
+
regions' --card-inset margins into a doubled gap instead of the
|
|
87
|
+
single inset block flow would have collapsed them to. The leading
|
|
88
|
+
region's own margin-bottom already supplies that inset; zero the
|
|
89
|
+
trailing region's margin-top. footer is excluded — its margin-top is
|
|
90
|
+
handled above (bottom-pin `auto`) or by [divider] below. */
|
|
91
|
+
:scope:has(> footer) > :is(header, section) + :is(header, section) {
|
|
92
|
+
margin-block-start: 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
83
95
|
/* ═══════ Variants — token-only overrides ═══════ */
|
|
84
96
|
|
|
85
97
|
/* `outline` is a documented alias for `outlined` (yaml). */
|
|
@@ -385,6 +397,30 @@
|
|
|
385
397
|
border-radius: 0;
|
|
386
398
|
}
|
|
387
399
|
|
|
400
|
+
/* Guide/value/legend safety inset (gh#1095) — [bleed]'s zero-inset is
|
|
401
|
+
only collision-free for the bare-marks case: a sparkline (its
|
|
402
|
+
renderer never emits axis ticks, gridlines, value labels, or a
|
|
403
|
+
legend — chart.class.js #renderSparkline), or any other chart-ui
|
|
404
|
+
type with BOTH [hide-grid] and [hide-values] set (the author opted
|
|
405
|
+
out of every text element). A chart that still draws guides or
|
|
406
|
+
value text — or is paired with a <chart-legend-ui> — needs
|
|
407
|
+
clearance from the card's frame, or that text collides with the
|
|
408
|
+
card edge and clips under the corner-rounded `overflow: hidden`
|
|
409
|
+
(:scope, top of file). Restore the card's own inset automatically
|
|
410
|
+
for those cases rather than relying on every author to remember —
|
|
411
|
+
the :has() selector's specificity already beats the plain [bleed]
|
|
412
|
+
reset above regardless of source order. Pairing a legend with a
|
|
413
|
+
genuinely full-bleed chart still works — put the legend in its OWN
|
|
414
|
+
section below, wired via chart-legend-ui[for="<chart id>"], which
|
|
415
|
+
never enters this selector (see chart-in-card.examples.html's
|
|
416
|
+
"Full-bleed chart + legend band" example). */
|
|
417
|
+
& > section[bleed]:has(> chart-ui:not([type="sparkline"]):not([hide-grid])),
|
|
418
|
+
& > section[bleed]:has(> chart-ui:not([type="sparkline"]):not([hide-values])),
|
|
419
|
+
& > section[bleed]:has(> chart-legend-ui) {
|
|
420
|
+
margin: var(--card-inset);
|
|
421
|
+
padding: 0;
|
|
422
|
+
}
|
|
423
|
+
|
|
388
424
|
/* ═══════ Footer ═══════
|
|
389
425
|
Margin-based inset. Flex row for actions.
|
|
390
426
|
[divider] adds top border.
|
|
@@ -414,8 +450,15 @@
|
|
|
414
450
|
justify-content: flex-end;
|
|
415
451
|
}
|
|
416
452
|
|
|
453
|
+
/* Divider clearance is padding-only (matches header[divider]'s
|
|
454
|
+
padding-bottom pattern) — the space above the line already comes from
|
|
455
|
+
the preceding section's own trailing margin. An explicit margin-top
|
|
456
|
+
here on top of that stacked with the footer's base margin instead of
|
|
457
|
+
collapsing into it (footer/section are flex-column siblings once the
|
|
458
|
+
card has a footer — see the :has(> footer) rule above — so adjacent
|
|
459
|
+
margins never collapse), tripling the gap to the divider vs. the
|
|
460
|
+
content gaps around it (gh#1096). */
|
|
417
461
|
& > footer[divider] {
|
|
418
|
-
margin-top: var(--card-inset);
|
|
419
462
|
padding-top: var(--card-inset);
|
|
420
463
|
border-top: 1px solid var(--card-divider);
|
|
421
464
|
}
|
|
@@ -46,6 +46,11 @@
|
|
|
46
46
|
"type": "string",
|
|
47
47
|
"default": ""
|
|
48
48
|
},
|
|
49
|
+
"labelHidden": {
|
|
50
|
+
"description": "When true, [label] still sets the accessible name (aria-label) but the visible text is suppressed via the canonical sr-only technique (gh#1010). Use when a sibling element already shows the same name visually (e.g. a title next to a check-ui used as a list-item icon) and the plain-visible label would paint it twice.",
|
|
51
|
+
"type": "boolean",
|
|
52
|
+
"default": false
|
|
53
|
+
},
|
|
49
54
|
"name": {
|
|
50
55
|
"description": "Form field name",
|
|
51
56
|
"type": "string",
|
|
@@ -123,26 +128,35 @@
|
|
|
123
128
|
},
|
|
124
129
|
"tag": "check-ui",
|
|
125
130
|
"tokens": {
|
|
126
|
-
"--check-
|
|
131
|
+
"--check-bg": {
|
|
127
132
|
"description": "Unchecked background"
|
|
128
133
|
},
|
|
129
|
-
"--check-
|
|
130
|
-
"description": "
|
|
134
|
+
"--check-bg-checked": {
|
|
135
|
+
"description": "Checked/indeterminate background"
|
|
131
136
|
},
|
|
132
|
-
"--check-
|
|
133
|
-
"description": "
|
|
137
|
+
"--check-bg-checked-hover": {
|
|
138
|
+
"description": "Checked/indeterminate background on hover"
|
|
134
139
|
},
|
|
135
|
-
"--check-
|
|
136
|
-
"description": "
|
|
140
|
+
"--check-bg-hover": {
|
|
141
|
+
"description": "Unchecked background on hover"
|
|
137
142
|
},
|
|
138
|
-
"--check-
|
|
139
|
-
"description": "
|
|
143
|
+
"--check-border": {
|
|
144
|
+
"description": "Unchecked border color"
|
|
140
145
|
},
|
|
141
|
-
"--check-
|
|
146
|
+
"--check-border-checked": {
|
|
142
147
|
"description": "Checked/indeterminate border"
|
|
143
148
|
},
|
|
144
|
-
"--check-
|
|
149
|
+
"--check-border-hover": {
|
|
150
|
+
"description": "Unchecked border color on hover"
|
|
151
|
+
},
|
|
152
|
+
"--check-fg-checked": {
|
|
145
153
|
"description": "Checkmark/dash color"
|
|
154
|
+
},
|
|
155
|
+
"--check-radius": {
|
|
156
|
+
"description": "Checkbox border radius"
|
|
157
|
+
},
|
|
158
|
+
"--check-size": {
|
|
159
|
+
"description": "Checkbox indicator size"
|
|
146
160
|
}
|
|
147
161
|
},
|
|
148
162
|
"traits": [],
|
|
@@ -26,6 +26,11 @@ export class UICheck extends UIFormElement {
|
|
|
26
26
|
checked: { type: Boolean, default: false, reflect: true },
|
|
27
27
|
indeterminate: { type: Boolean, default: false, reflect: true },
|
|
28
28
|
label: { type: String, default: '', reflect: true },
|
|
29
|
+
/* gh#1010: keeps [label] as the accessible name (aria-label, set
|
|
30
|
+
below) while suppressing the VISIBLE `::after` text — for
|
|
31
|
+
compositions that already show the name elsewhere (e.g. a
|
|
32
|
+
sibling title) and would otherwise paint it twice. */
|
|
33
|
+
labelHidden: { type: Boolean, default: false, reflect: true, attribute: 'label-hidden' },
|
|
29
34
|
};
|
|
30
35
|
|
|
31
36
|
static template = () => html`<span slot="box"></span>`;
|
|
@@ -122,6 +122,27 @@ check-ui[indeterminate] {
|
|
|
122
122
|
/* Label */
|
|
123
123
|
:scope[label]::after { content: attr(label); }
|
|
124
124
|
|
|
125
|
+
/* Visually-hidden label (gh#1010) — [label-hidden] keeps the a11y name
|
|
126
|
+
(aria-label, set from [label] in check.class.js render()) but drops
|
|
127
|
+
the visible text, for compositions that already show the name
|
|
128
|
+
elsewhere. Same canonical sr-only recipe as <visually-hidden-ui>
|
|
129
|
+
(visually-hidden.css) — clip-path does the real hiding; the rest is
|
|
130
|
+
belt-and-suspenders for cross-UA. More specific than the bare
|
|
131
|
+
`[label]::after` rule above, so it wins whenever both are set. */
|
|
132
|
+
:scope[label][label-hidden]::after {
|
|
133
|
+
content: attr(label);
|
|
134
|
+
position: absolute !important;
|
|
135
|
+
width: 1px !important;
|
|
136
|
+
height: 1px !important;
|
|
137
|
+
padding: 0 !important;
|
|
138
|
+
margin: -1px !important;
|
|
139
|
+
overflow: hidden !important;
|
|
140
|
+
clip: rect(0, 0, 0, 0) !important;
|
|
141
|
+
clip-path: inset(100%) !important;
|
|
142
|
+
white-space: nowrap !important;
|
|
143
|
+
border: 0 !important;
|
|
144
|
+
}
|
|
145
|
+
|
|
125
146
|
/* Focus */
|
|
126
147
|
:scope:focus-visible [slot="box"] { box-shadow: var(--check-focus-ring); border-color: transparent; }
|
|
127
148
|
|
|
@@ -20,6 +20,8 @@ export class UICheck extends UIFormElement {
|
|
|
20
20
|
/** Indeterminate (mixed) state — visual only; cleared on click. */
|
|
21
21
|
indeterminate: boolean;
|
|
22
22
|
label: string;
|
|
23
|
+
/** When true, [label] still sets the accessible name but the visible text is sr-only hidden (gh#1010). */
|
|
24
|
+
labelHidden: boolean;
|
|
23
25
|
|
|
24
26
|
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
25
27
|
type: K,
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
```html
|
|
12
12
|
<row-ui gap="6" align="start" wrap>
|
|
13
13
|
<col-ui gap="2">
|
|
14
|
-
<text-ui variant="caption" color="muted">
|
|
15
|
-
<div
|
|
14
|
+
<text-ui variant="caption" color="muted">scale="ui-sm"</text-ui>
|
|
15
|
+
<div scale="ui-sm">
|
|
16
16
|
<check-ui label="Notify me" checked></check-ui>
|
|
17
17
|
</div>
|
|
18
18
|
</col-ui>
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
</col-ui>
|
|
25
25
|
<col-ui gap="2">
|
|
26
|
-
<text-ui variant="caption" color="muted">
|
|
27
|
-
<div
|
|
26
|
+
<text-ui variant="caption" color="muted">scale="content-md"</text-ui>
|
|
27
|
+
<div scale="content-md">
|
|
28
28
|
<check-ui label="Notify me" checked></check-ui>
|
|
29
29
|
</div>
|
|
30
30
|
</col-ui>
|
|
@@ -48,6 +48,17 @@ props:
|
|
|
48
48
|
required: true
|
|
49
49
|
type: string
|
|
50
50
|
default: ""
|
|
51
|
+
labelHidden:
|
|
52
|
+
description: >-
|
|
53
|
+
When true, [label] still sets the accessible name (aria-label) but
|
|
54
|
+
the visible text is suppressed via the canonical sr-only technique
|
|
55
|
+
(gh#1010). Use when a sibling element already shows the same name
|
|
56
|
+
visually (e.g. a title next to a check-ui used as a list-item icon)
|
|
57
|
+
and the plain-visible label would paint it twice.
|
|
58
|
+
type: boolean
|
|
59
|
+
default: false
|
|
60
|
+
reflect: true
|
|
61
|
+
attribute: label-hidden
|
|
51
62
|
value:
|
|
52
63
|
description: Form value (submitted as 'on' when checked)
|
|
53
64
|
type: string
|
|
@@ -68,23 +79,31 @@ states:
|
|
|
68
79
|
attribute: disabled
|
|
69
80
|
traits: []
|
|
70
81
|
tokens:
|
|
71
|
-
--check-
|
|
82
|
+
--check-bg:
|
|
72
83
|
description: Unchecked background
|
|
73
|
-
--check-
|
|
84
|
+
--check-border:
|
|
74
85
|
description: Unchecked border color
|
|
75
|
-
--check-
|
|
86
|
+
--check-radius:
|
|
76
87
|
description: Checkbox border radius
|
|
77
|
-
--check-
|
|
88
|
+
--check-size:
|
|
78
89
|
description: Checkbox indicator size
|
|
79
|
-
--check-checked
|
|
90
|
+
--check-bg-checked:
|
|
80
91
|
description: Checked/indeterminate background
|
|
81
|
-
--check-
|
|
92
|
+
--check-border-checked:
|
|
82
93
|
description: Checked/indeterminate border
|
|
83
|
-
--check-checked
|
|
94
|
+
--check-fg-checked:
|
|
84
95
|
description: Checkmark/dash color
|
|
96
|
+
--check-border-hover:
|
|
97
|
+
description: Unchecked border color on hover
|
|
98
|
+
--check-bg-hover:
|
|
99
|
+
description: Unchecked background on hover
|
|
100
|
+
--check-bg-checked-hover:
|
|
101
|
+
description: Checked/indeterminate background on hover
|
|
85
102
|
a2ui:
|
|
86
103
|
rules:
|
|
87
104
|
- "Self-labeling widget — use the [label] attribute directly; do NOT wrap in <field-ui>. The widget renders its own label inline via CSS attr() pattern. Wrapping breaks the consent-row layout (see field-ui anti_patterns)."
|
|
105
|
+
- rule: 'When check-ui is used as a list-item icon/indicator beside a separate title element carrying the same name (a title column, a list-item-ui slot="text"), set [label-hidden] alongside [label] so the accessible name is preserved without painting the name twice.'
|
|
106
|
+
reason: 'gh#1010 — the visible ::after label and an adjacent title both showed the step name, and the visible labels varied width, producing a ragged title column.'
|
|
88
107
|
- rule: 'Three states supported: unchecked (default), checked (via [checked]), and indeterminate (via [indeterminate]); form-associated.'
|
|
89
108
|
reason: 'Per ADR-0025 — host IS the control, no wrapped <input>.'
|
|
90
109
|
- rule: 'For binary on/off toggles where visual switch metaphor matters, use <switch-ui> instead; check-ui is for multi-select sets and form-acceptance gates.'
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
|
|
40
40
|
/* -- Header bar -- */
|
|
41
41
|
[slot="bar"] {
|
|
42
|
+
/* ensure('bar') APPENDS the bar after the authored slot content —
|
|
43
|
+
flex order puts it visually first (gh#1075: it rendered at the
|
|
44
|
+
bottom of the card, under the stage, without this). */
|
|
45
|
+
order: -1;
|
|
42
46
|
width: 100%;
|
|
43
47
|
padding: var(--demo-toggle-bar-py) var(--demo-toggle-bar-px);
|
|
44
48
|
background: var(--demo-toggle-bar-bg);
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
```html
|
|
6
6
|
<demo-toggle-ui label-on="With trait" label-off="Without trait" initial="off">
|
|
7
|
-
<div slot="off" style="
|
|
8
|
-
<div slot="on" style="
|
|
7
|
+
<div slot="off" style="text-align:center;color:var(--a-fg-muted);">Bare surface — no trait attached.</div>
|
|
8
|
+
<div slot="on" style="text-align:center;color:var(--md-sys-color-neutral-on-surface);">Same surface, with trait attached.</div>
|
|
9
9
|
</demo-toggle-ui>
|
|
10
10
|
```
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
```html
|
|
15
15
|
<demo-toggle-ui label-on="With shimmer-loading" label-off="Without shimmer-loading">
|
|
16
|
-
<div slot="off"
|
|
17
|
-
<div slot="on"
|
|
16
|
+
<div slot="off">Placeholder content (no trait)</div>
|
|
17
|
+
<div slot="on">Placeholder content (shimmer active)</div>
|
|
18
18
|
</demo-toggle-ui>
|
|
19
19
|
```
|
|
@@ -47,14 +47,15 @@
|
|
|
47
47
|
"default": ""
|
|
48
48
|
},
|
|
49
49
|
"variant": {
|
|
50
|
-
"description": "Semantic variant",
|
|
50
|
+
"description": "Semantic variant — `default | info | success | warning | danger | primary`. `primary` is the brand-emphasis fill (accent-filled bg + on-accent text), ported from toast.css's `primary` variant (gh#1104) now that feed-item-ui is the real paint site for posted toasts.",
|
|
51
51
|
"type": "string",
|
|
52
52
|
"enum": [
|
|
53
53
|
"default",
|
|
54
54
|
"info",
|
|
55
55
|
"success",
|
|
56
56
|
"warning",
|
|
57
|
-
"danger"
|
|
57
|
+
"danger",
|
|
58
|
+
"primary"
|
|
58
59
|
],
|
|
59
60
|
"default": "default"
|
|
60
61
|
}
|
|
@@ -25,7 +25,12 @@ props:
|
|
|
25
25
|
type: string
|
|
26
26
|
default: ""
|
|
27
27
|
variant:
|
|
28
|
-
description:
|
|
28
|
+
description: >-
|
|
29
|
+
Semantic variant — `default | info | success | warning | danger |
|
|
30
|
+
primary`. `primary` is the brand-emphasis fill (accent-filled bg +
|
|
31
|
+
on-accent text), ported from toast.css's `primary` variant
|
|
32
|
+
(gh#1104) now that feed-item-ui is the real paint site for
|
|
33
|
+
posted toasts.
|
|
29
34
|
type: string
|
|
30
35
|
default: default
|
|
31
36
|
enum:
|
|
@@ -34,6 +39,7 @@ props:
|
|
|
34
39
|
- success
|
|
35
40
|
- warning
|
|
36
41
|
- danger
|
|
42
|
+
- primary
|
|
37
43
|
duration:
|
|
38
44
|
description: Auto-fade timer in ms; null/0 = sticky (requires user input)
|
|
39
45
|
type: number
|
package/components/feed/feed.css
CHANGED
|
@@ -99,7 +99,16 @@ feed-item-ui[data-closing] {
|
|
|
99
99
|
/* Item — atomic feed entry. */
|
|
100
100
|
@scope (feed-item-ui) {
|
|
101
101
|
:where(:scope) {
|
|
102
|
-
|
|
102
|
+
/* -container-high (NOT plain -background/-container) — a top-layer
|
|
103
|
+
overlay item needs a tonal step strong enough to read as its own
|
|
104
|
+
elevated surface against arbitrary page content behind it
|
|
105
|
+
(gh#1091). Plain -background is literally the page's own bg
|
|
106
|
+
token, so an un-varianted item had ZERO tonal separation. Every
|
|
107
|
+
family (incl. neutral) has a generated -container-high role in
|
|
108
|
+
colors/material-static.css — the same tier `--a-{family}-subtle`
|
|
109
|
+
aliases to (component-token-contract.md's `-strong` semantics
|
|
110
|
+
note). */
|
|
111
|
+
--feed-item-bg: var(--md-sys-color-neutral-container-high);
|
|
103
112
|
--feed-item-fg: var(--md-sys-color-neutral-on-surface);
|
|
104
113
|
--feed-item-border: var(--md-sys-color-neutral-outline-variant);
|
|
105
114
|
--feed-item-radius: var(--a-radius-md);
|
|
@@ -117,10 +126,20 @@ feed-item-ui[data-closing] {
|
|
|
117
126
|
NOT --a-{variant}-fg (= --a-{variant}-text-strong, locked for solid
|
|
118
127
|
--variant-strong fills) — pairing a locked fg with a flipping bg goes
|
|
119
128
|
low-contrast in one scheme. Mirrors alert.css + toast.css wiring. */
|
|
120
|
-
:scope[variant="info"] { --feed-item-fg: var(--md-sys-color-info-on-surface); --feed-item-bg: var(--md-sys-color-info-container); }
|
|
121
|
-
:scope[variant="success"] { --feed-item-fg: var(--md-sys-color-success-on-surface); --feed-item-bg: var(--md-sys-color-success-container); }
|
|
122
|
-
:scope[variant="warning"] { --feed-item-fg: var(--md-sys-color-warning-on-surface); --feed-item-bg: var(--md-sys-color-warning-container); }
|
|
123
|
-
:scope[variant="danger"] { --feed-item-fg: var(--md-sys-color-danger-on-surface); --feed-item-bg: var(--md-sys-color-danger-container); }
|
|
129
|
+
:scope[variant="info"] { --feed-item-fg: var(--md-sys-color-info-on-surface); --feed-item-bg: var(--md-sys-color-info-container-high); }
|
|
130
|
+
:scope[variant="success"] { --feed-item-fg: var(--md-sys-color-success-on-surface); --feed-item-bg: var(--md-sys-color-success-container-high); }
|
|
131
|
+
:scope[variant="warning"] { --feed-item-fg: var(--md-sys-color-warning-on-surface); --feed-item-bg: var(--md-sys-color-warning-container-high); }
|
|
132
|
+
:scope[variant="danger"] { --feed-item-fg: var(--md-sys-color-danger-on-surface); --feed-item-bg: var(--md-sys-color-danger-container-high); }
|
|
133
|
+
/* `primary` — the accent-filled "branded" tone (welcome banners,
|
|
134
|
+
feature-launch nudges), ported from toast.css's `primary` variant
|
|
135
|
+
(gh#1104 — toast.css documented this but its rules never paint;
|
|
136
|
+
feed-item-ui is the real render surface post-migration). No
|
|
137
|
+
border override, matching this block's existing two-property
|
|
138
|
+
shape (unlike toast.css's variant block, which does override
|
|
139
|
+
border). Deliberately NOT the -container-high convention above —
|
|
140
|
+
primary is a stronger/bolder branded solid-fill per gh#1104's own
|
|
141
|
+
acceptance criteria, not a softer semantic-status tone. */
|
|
142
|
+
:scope[variant="primary"] { --feed-item-fg: var(--md-sys-color-primary-on-primary); --feed-item-bg: var(--a-primary-bg); }
|
|
124
143
|
|
|
125
144
|
:scope {
|
|
126
145
|
box-sizing: border-box;
|
|
@@ -143,6 +162,10 @@ feed-item-ui[data-closing] {
|
|
|
143
162
|
opacity: 0;
|
|
144
163
|
transform: translateY(0.5rem);
|
|
145
164
|
pointer-events: auto;
|
|
165
|
+
/* Elevated-surface separation over busy page content (gh#1091) —
|
|
166
|
+
mirrors loading-overlay.css's [variant="blur"] treatment. */
|
|
167
|
+
backdrop-filter: blur(4px);
|
|
168
|
+
-webkit-backdrop-filter: blur(4px);
|
|
146
169
|
}
|
|
147
170
|
:scope [slot="body"] {
|
|
148
171
|
flex: 1;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
```html
|
|
14
14
|
<row-ui gap="6" align="start" wrap>
|
|
15
15
|
<col-ui gap="2">
|
|
16
|
-
<text-ui variant="caption" color="muted">
|
|
17
|
-
<div
|
|
16
|
+
<text-ui variant="caption" color="muted">scale="ui-sm"</text-ui>
|
|
17
|
+
<div scale="ui-sm" style="width:220px">
|
|
18
18
|
<field-ui label="Email">
|
|
19
19
|
<input-ui type="email" placeholder="you@example.com"></input-ui>
|
|
20
20
|
</field-ui>
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
</div>
|
|
30
30
|
</col-ui>
|
|
31
31
|
<col-ui gap="2">
|
|
32
|
-
<text-ui variant="caption" color="muted">
|
|
33
|
-
<div
|
|
32
|
+
<text-ui variant="caption" color="muted">scale="content-md"</text-ui>
|
|
33
|
+
<div scale="content-md" style="width:220px">
|
|
34
34
|
<field-ui label="Email">
|
|
35
35
|
<input-ui type="email" placeholder="you@example.com"></input-ui>
|
|
36
36
|
</field-ui>
|
|
@@ -66,6 +66,14 @@ export class UIImage extends UIElement {
|
|
|
66
66
|
}
|
|
67
67
|
this.#img.addEventListener('load', this.#onLoad);
|
|
68
68
|
this.#img.addEventListener('error', this.#onError);
|
|
69
|
+
// Missed-load guard (gh#999): an image already complete when these
|
|
70
|
+
// listeners attach — a parse-time-loaded authored [slot="image"], or a
|
|
71
|
+
// cache hit racing the upgrade — fired `load` before we were listening.
|
|
72
|
+
// Without this check [data-loaded] never stamps and the reveal
|
|
73
|
+
// (skeleton → img opacity 1) never happens: the permanent blank box
|
|
74
|
+
// gh#988 reported. naturalWidth guards the broken-image case, which
|
|
75
|
+
// fires `error` (still listened) rather than a false reveal.
|
|
76
|
+
if (this.#img.complete && this.#img.naturalWidth > 0) this.#onLoad();
|
|
69
77
|
|
|
70
78
|
this.#applySize();
|
|
71
79
|
}
|
|
@@ -28,6 +28,14 @@
|
|
|
28
28
|
--nav-group-bg-selected: var(--a-bg-selected); /* mirrors --nav-item-bg-selected (gh#795) */
|
|
29
29
|
--nav-group-icon-size: calc(var(--nav-group-row-height) - var(--a-space-2));
|
|
30
30
|
--nav-group-badge-size: var(--a-ui-sm);
|
|
31
|
+
/* Continuous indent rail color (gh#1016) — was referenced at the
|
|
32
|
+
::after usage site below but never given a base value here, the
|
|
33
|
+
same empty-var failure class --nav-gap already documents in this
|
|
34
|
+
file: an undefined custom property resolves to the guaranteed-
|
|
35
|
+
invalid value, so `background: var(--nav-group-indent-rail-bg)`
|
|
36
|
+
painted nothing. Same house role accordion, agent- components,
|
|
37
|
+
chart etc. use for subtle structural lines. */
|
|
38
|
+
--nav-group-indent-rail-bg: var(--md-sys-color-neutral-outline-variant);
|
|
31
39
|
|
|
32
40
|
--nav-item-child-height: var(--a-size-sm);
|
|
33
41
|
--nav-item-child-font: var(--nav-group-font-size);
|
|
@@ -57,7 +65,10 @@
|
|
|
57
65
|
top: var(--nav-group-row-height);
|
|
58
66
|
bottom: calc(var(--nav-group-row-height) / 2);
|
|
59
67
|
width: 1px;
|
|
60
|
-
|
|
68
|
+
/* Explicit fallback — same defensive shape --nav-gap got above —
|
|
69
|
+
so an ancestor/override cascade that sets this token to an empty
|
|
70
|
+
string still paints a rail instead of silently disappearing. */
|
|
71
|
+
background: var(--nav-group-indent-rail-bg, var(--md-sys-color-neutral-outline-variant));
|
|
61
72
|
pointer-events: none;
|
|
62
73
|
}
|
|
63
74
|
/* Selected-look header treatment keys on [selected] — the CSS half of
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://adiaui.dev/a2ui/v0_9/components/OptionCard.json",
|
|
4
4
|
"title": "OptionCard",
|
|
5
|
-
"description": "Selectable card with radio semantics. A \"rich radio\" — single-select one of N where each option carries a heading, optional description, and optional
|
|
5
|
+
"description": "Selectable card with radio semantics. A \"rich radio\" — single-select one of N where each option carries a heading, optional description, and an optional icon at the trailing end of the header row. Siblings sharing a `name` form a radiogroup. The whole card is the click target; a CSS-rendered radio circle in the top-left signals state. Renders on a container-low tonal surface (no outline as the primary boundary); the checked state keeps an accent border + fill so selection stays unmistakable. Form-associated, so `name=value` submits with the parent form when checked.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"allOf": [
|
|
8
8
|
{
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
"default": ""
|
|
43
43
|
},
|
|
44
44
|
"icon": {
|
|
45
|
-
"description": "Optional Phosphor icon name. Stamped as a
|
|
45
|
+
"description": "Optional Phosphor icon name. Stamped as a trailing <icon-ui slot=\"icon\"> when set.",
|
|
46
46
|
"type": "string",
|
|
47
47
|
"default": ""
|
|
48
48
|
},
|
|
49
49
|
"layout": {
|
|
50
|
-
"description": "Internal layout. `default` puts the indicator on the left and the icon
|
|
50
|
+
"description": "Internal layout. `default` puts the indicator on the left and, when [icon] is set, the icon at the trailing end of the header row alongside the heading. `tile` stacks vertically — icon top-left, indicator top-right, heading + description below — for hero pickers (source / role / plan tiles) where the icon is a primary brand cue.",
|
|
51
51
|
"type": "string",
|
|
52
52
|
"enum": [
|
|
53
53
|
"default",
|
|
@@ -171,22 +171,22 @@
|
|
|
171
171
|
"tag": "option-card-ui",
|
|
172
172
|
"tokens": {
|
|
173
173
|
"--option-card-bg": {
|
|
174
|
-
"description": "Default background."
|
|
174
|
+
"description": "Default background (container-low tonal surface, gh#1018)."
|
|
175
175
|
},
|
|
176
176
|
"--option-card-bg-checked": {
|
|
177
177
|
"description": "Background when checked."
|
|
178
178
|
},
|
|
179
179
|
"--option-card-bg-hover": {
|
|
180
|
-
"description": "Hover background (non-checked)."
|
|
180
|
+
"description": "Hover background (non-checked) — one tonal step up from --option-card-bg so hover stays visibly distinct."
|
|
181
181
|
},
|
|
182
182
|
"--option-card-border": {
|
|
183
|
-
"description": "Default border color."
|
|
183
|
+
"description": "Default border color (transparent — the tonal bg is the primary boundary, not an outline; gh#1018)."
|
|
184
184
|
},
|
|
185
185
|
"--option-card-border-checked": {
|
|
186
186
|
"description": "Border color when checked."
|
|
187
187
|
},
|
|
188
188
|
"--option-card-border-hover": {
|
|
189
|
-
"description": "Hover border color (non-checked)."
|
|
189
|
+
"description": "Hover border color (non-checked; transparent by default, matching the no-outline base)."
|
|
190
190
|
},
|
|
191
191
|
"--option-card-desc-color": {
|
|
192
192
|
"description": "Description text color."
|
|
@@ -228,13 +228,13 @@
|
|
|
228
228
|
"description": "Heading font weight."
|
|
229
229
|
},
|
|
230
230
|
"--option-card-icon-color": {
|
|
231
|
-
"description": "
|
|
231
|
+
"description": "Trailing icon color when the card is not checked."
|
|
232
232
|
},
|
|
233
233
|
"--option-card-icon-color-checked": {
|
|
234
|
-
"description": "
|
|
234
|
+
"description": "Trailing icon color when the card is checked."
|
|
235
235
|
},
|
|
236
236
|
"--option-card-icon-size": {
|
|
237
|
-
"description": "
|
|
237
|
+
"description": "Trailing icon size (sets `--a-icon-size` on the slotted icon-ui)."
|
|
238
238
|
},
|
|
239
239
|
"--option-card-padding-block": {
|
|
240
240
|
"description": "Vertical padding inside the card."
|