@adia-ai/web-components 0.8.33 → 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 +33 -0
- package/components/agent-questions/agent-questions.class.js +0 -1
- package/components/agent-reasoning/agent-reasoning.a2ui.json +1 -1
- package/components/agent-reasoning/agent-reasoning.yaml +3 -3
- package/components/badge/badge.css +33 -7
- package/components/badge/badge.examples.md +4 -4
- package/components/button/button.css +12 -0
- 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/combobox/combobox.a2ui.json +1 -1
- package/components/combobox/combobox.yaml +3 -0
- package/components/command/command.a2ui.json +4 -0
- package/components/command/command.class.js +54 -4
- package/components/command/command.d.ts +2 -0
- package/components/command/command.yaml +25 -3
- package/components/date-range-picker/date-range-picker.a2ui.json +1 -1
- package/components/date-range-picker/date-range-picker.class.js +42 -43
- package/components/date-range-picker/date-range-picker.css +11 -0
- package/components/date-range-picker/date-range-picker.yaml +6 -3
- package/components/demo-toggle/demo-toggle.css +4 -0
- package/components/demo-toggle/demo-toggle.examples.md +4 -4
- package/components/description-list/description-list.css +16 -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/modal/modal.class.js +43 -2
- package/components/modal/modal.css +23 -0
- package/components/nav-group/nav-group.css +27 -5
- package/components/nav-item/nav-item.css +11 -3
- 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/richtext/richtext.css +5 -1
- package/components/segment/segment.css +10 -0
- 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/step-progress/step-progress.css +16 -3
- package/components/swatch/swatch.css +14 -6
- package/components/switch/switch.examples.md +4 -4
- package/components/table/cell-types.js +8 -0
- package/components/table/table.a2ui.json +1 -1
- package/components/table/table.class.js +11 -0
- package/components/table/table.css +9 -0
- package/components/table/table.d.ts +1 -1
- package/components/table/table.yaml +1 -1
- package/components/table-toolbar/table-toolbar.css +10 -1
- package/components/tabs/tabs.css +13 -5
- package/components/tag/tag.class.js +14 -1
- package/components/tag/tag.css +70 -9
- 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/core/element.js +31 -0
- package/core/signals.js +3 -1
- package/custom-elements.json +469 -46
- package/dist/theme-provider.min.js +2 -2
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +41 -41
- 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 +135 -147
- 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/styles/colors/semantics/core.css +22 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
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
|
+
|
|
12
|
+
## [0.8.34] — 2026-08-11
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **`date-range-picker-ui` — both calendar grids are now ONE click-start-click-end selection surface (gh#948, reported from adiav2 ADIA2-8020).** The change handlers were role-locked per pane (`from`-pane clicks could only ever write the range start), so a same-month range required paging the right pane back a month. First click = start, second = end in either grid; a second click earlier than the pending start restarts there; a click after a committed range starts fresh. Popover content-sizing (`width: max-content` + viewport/token caps) moved into the stylesheet so the JS anchor fallback and anchoring failures can no longer render a viewport-huge panel.
|
|
17
|
+
- **`UIElement` — `reflect:true` booleans with a TRUE default now stamp their attribute on connect (gh#961).** installProps seeds the signal but can't write attributes (constructor restriction), and the setter's `Object.is` short-circuit skips reflection on same-value sets — so attribute-keyed CSS (`chat-thread:not([empty]) > chat-empty`, `editor-canvas:not([empty]) > editor-canvas-empty`, password-strength's `:not([show-label])`) read wrong state forever; 9 components carried the latent shape. The connect-time pre-sync loop now runs inside `untracked()` — its property reads otherwise subscribe a PARENT's render effect to template-created children's signals, the unbounded re-stamp oscillation the signals drain guard traps (the guard now names the still-dirty effect hosts).
|
|
18
|
+
- **`modal-ui` — `aria-labelledby` falls back to an authored `[slot="heading"]` when `text=` is absent (gh#947), and an authored bare `<header>` no longer displaces into the body (gh#941).** Header icon+heading row layout is by tag + DOM order: the last non-button child claims the row, earlier content stays fixed-width.
|
|
19
|
+
- **`table-ui` — composite-cell wrapper flex generalized to CSS (gh#940):** `[data-body] [role="gridcell"] > row-ui { flex: 1 }` covers progress AND avatar cells; the progress bar no longer collapses to ~33px. `<col-def meta>` JSON attribute carries per-column config (badge variant maps) declaratively.
|
|
20
|
+
- **`step-progress-ui` — direction-agnostic sizing (gh#942):** `inline-size: 18rem` + `max-inline-size: 100%` replace the direction-fragile `flex-basis`, so a column-flex parent no longer inflates the component to 288px tall.
|
|
21
|
+
- **`command-ui` / `combobox-ui` — `options` catalog schema corrected to rich objects (`DynamicObjectList`).** Both yamls declare `{value, label, icon?, …}` objects but omitted `items.type`, mapping to the string-list default — the dialect validator rejected every harvested rich-options palette (caught by exit-gate.corpus at release pre-flight).
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`richtext` — inline `<code>` chip background softened to container-low (gh#972):** the opaque `--a-canvas-2` chip out-competed body text where several tag references cluster; the 10% alpha tier recedes behind prose and composites consistently on stacked surfaces. The docs site's own `admin-page code` rule moves to the same tier (superseding its earlier well-strong non-text-contrast ruling — inline code is text formatting, not a UI component).
|
|
26
|
+
- **`nav-item-ui` / `nav-group-ui` — state color spec (gh#968, operator ruling):** idle = neutral icons + neutral-high text on transparent; hover = on-surface on container-low; selected = on-surface on container. Selected glyphs drop the primary accent (supersedes gh#522's glyph half — the accent BAR keeps primary); `neutral/surfaceBright` was considered for the selected fill and ruled out.
|
|
27
|
+
- **`tag-ui` / `badge-ui` / `tabs-ui` — font scale steps one rung (gh#965):** tag/badge default `--a-ui-sm` → `--a-ui-xs` with tiers shifting to `--a-ui-2xs`/`--a-ui-sm` (first consumer of the pre-staged 10px token); tabs `--a-ui-md` → `--a-ui-lg`.
|
|
28
|
+
- **`description-list-ui` — `dt` renders as a kicker/data-label** (code family at `--a-label-size`, normal weight); **`dd` is semibold at context-inherited size** (`1em`) so the value leads the pair and tracks the surrounding prose.
|
|
29
|
+
- **Token docs — the `-strong` semantics split documented (gh#969):** `--a-canvas-strong` is a surface-tonal tier while interactive families' `-strong` is the pressed/high-emphasis foreground — noted at the core.css declarations and in component-token-contract.md. No value changes.
|
|
30
|
+
|
|
31
|
+
### Maintenance
|
|
32
|
+
- **`dist/` bundles rebuilt** in this cut's window (4 file(s)) — regenerated from the source changes described above, not independent edits.
|
|
33
|
+
- **`patterns/` touched in this release window** (1 file(s), e.g. `responsive-shell-sidebar/responsive-shell-sidebar.examples.html`) — carried by the entries above.
|
|
34
|
+
- **`styles/` touched in this release window** (1 file(s), e.g. `semantics/core.css`) — carried by the entries above.
|
|
35
|
+
|
|
3
36
|
## [0.8.33] — 2026-08-11
|
|
4
37
|
|
|
5
38
|
### Added
|
|
@@ -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);
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
],
|
|
112
112
|
"slots": {
|
|
113
113
|
"default": {
|
|
114
|
-
"description": "Default slot —
|
|
114
|
+
"description": "Default slot — NOT a step-authoring surface: the component rebuilds its body from the addStep()/addThought() pipeline and does not consume authored children (gh#938)."
|
|
115
115
|
}
|
|
116
116
|
},
|
|
117
117
|
"states": [
|
|
@@ -57,7 +57,7 @@ events:
|
|
|
57
57
|
description: Whether the reasoning section is now collapsed.
|
|
58
58
|
slots:
|
|
59
59
|
default:
|
|
60
|
-
description: "Default slot —
|
|
60
|
+
description: "Default slot — NOT a step-authoring surface: the component rebuilds its body from the addStep()/addThought() pipeline and does not consume authored children (gh#938)."
|
|
61
61
|
states:
|
|
62
62
|
- name: idle
|
|
63
63
|
description: Default, ready for interaction.
|
|
@@ -72,8 +72,8 @@ a2ui:
|
|
|
72
72
|
rules:
|
|
73
73
|
- rule: 'Agent inner-monologue + pipeline viewer with steps, thoughts, plans, and iterations.'
|
|
74
74
|
reason: 'Reasoning visualization surface.'
|
|
75
|
-
- rule: '
|
|
76
|
-
reason: 'Composition contract.'
|
|
75
|
+
- rule: 'JS-property-driven ONLY — steps arrive via addStep()/addThought(); the component renders them internally as <timeline-item-ui> rows. Authored light-DOM children are NOT consumed (gh#938) — for a static/harvestable reasoning-steps surface, author a plain <timeline-ui> with <timeline-item-ui> children instead.'
|
|
76
|
+
reason: 'Composition contract — the previous wording ("pass reasoning steps as children") read as declarative-children support the class never had; a stateful pipeline (timers, spine layout, iterations) has no static form.'
|
|
77
77
|
- rule: 'noAutocollapse attribute prevents the auto-collapse-on-complete behavior; useful for debug surfaces.'
|
|
78
78
|
reason: 'Behavior knob.'
|
|
79
79
|
- rule: 'Different from <agent-trace-ui> (metrics + tool-call summary) — reasoning is narrative, trace is structured-data.'
|
|
@@ -20,9 +20,25 @@
|
|
|
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);
|
|
25
|
-
|
|
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 */
|
|
39
|
+
/* One rung down the --a-ui-* scale (gh#965) — ladder shifts with it
|
|
40
|
+
(sm=2xs, lg=sm) so tiers stay one rung apart. Mirrors tag-ui. */
|
|
41
|
+
--badge-font-size: var(--a-ui-xs);
|
|
26
42
|
/* ── Typographic register (issue 845; weight revised gh#866) — mono
|
|
27
43
|
TRIAL taken: kbd-ui's own stack (--a-font-family-code, kbd.css) held
|
|
28
44
|
up at small badge sizes (roughly a dozen logical pixels) in both
|
|
@@ -43,10 +59,13 @@
|
|
|
43
59
|
and tag share this md baseline and this exact reasoning). */
|
|
44
60
|
--badge-px-sm: var(--a-space-1);
|
|
45
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). */
|
|
46
65
|
--badge-py-sm: var(--a-space-px);
|
|
47
|
-
--badge-py-lg: var(--a-space-
|
|
48
|
-
--badge-font-size-sm: var(--a-ui-
|
|
49
|
-
--badge-font-size-lg: var(--a-ui-
|
|
66
|
+
--badge-py-lg: var(--a-space-0-5);
|
|
67
|
+
--badge-font-size-sm: var(--a-ui-2xs);
|
|
68
|
+
--badge-font-size-lg: var(--a-ui-sm);
|
|
50
69
|
text-align: start; /* §text-align-reset — blocks inheritance from centered ancestors */
|
|
51
70
|
}
|
|
52
71
|
|
|
@@ -58,6 +77,10 @@
|
|
|
58
77
|
justify-content: center;
|
|
59
78
|
gap: var(--badge-gap);
|
|
60
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);
|
|
61
84
|
padding: var(--badge-py) var(--badge-px);
|
|
62
85
|
background: var(--badge-bg);
|
|
63
86
|
color: var(--badge-fg);
|
|
@@ -237,15 +260,18 @@
|
|
|
237
260
|
--badge-px: var(--badge-px-sm);
|
|
238
261
|
--badge-py: var(--badge-py-sm);
|
|
239
262
|
--badge-font-size: var(--badge-font-size-sm);
|
|
263
|
+
--badge-min-h: var(--badge-min-h-sm);
|
|
240
264
|
}
|
|
241
265
|
:scope[size="md"] {
|
|
242
266
|
--badge-px: var(--a-space-1-5);
|
|
243
|
-
--badge-py: var(--a-space-
|
|
244
|
-
--badge-font-size: var(--a-ui-
|
|
267
|
+
--badge-py: var(--a-space-px);
|
|
268
|
+
--badge-font-size: var(--a-ui-xs);
|
|
269
|
+
--badge-min-h: 0.9375rem; /* 15px @ d=1 — matches the :where(:scope) default */
|
|
245
270
|
}
|
|
246
271
|
:scope[size="lg"] {
|
|
247
272
|
--badge-px: var(--badge-px-lg);
|
|
248
273
|
--badge-py: var(--badge-py-lg);
|
|
249
274
|
--badge-font-size: var(--badge-font-size-lg);
|
|
275
|
+
--badge-min-h: var(--badge-min-h-lg);
|
|
250
276
|
}
|
|
251
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>
|
|
@@ -84,6 +84,15 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
|
|
|
84
84
|
--button-font-size: var(--a-ui-size);
|
|
85
85
|
--button-font-weight: var(--a-ui-weight);
|
|
86
86
|
--button-font-family: var(--a-font-family-ui);
|
|
87
|
+
/* Leading for the [text] label box ONLY — never the host. The host's
|
|
88
|
+
`line-height: 1` is deliberate (it sizes the icon/[slot="trailing"]
|
|
89
|
+
blocks), but the label's ::after clips to its own line box, so
|
|
90
|
+
inheriting 1 makes half-leading negative and shears descenders
|
|
91
|
+
(g/j/p/q/y, parentheses) by ~0.93px at the default size — gh#906.
|
|
92
|
+
Snug (1.3) contains the font's content box at every [size]; the
|
|
93
|
+
precedent is stat.css:174,198 setting leading on the truncating
|
|
94
|
+
box rather than on the component root. */
|
|
95
|
+
--button-label-line-height: var(--a-leading-snug);
|
|
87
96
|
--button-gap: var(--a-space-1);
|
|
88
97
|
--button-bg-hover: var(--a-bg-strong); /* neutral fill → neutral -strong surface on hover */
|
|
89
98
|
--button-fg-hover: var(--a-ui-text-hover);
|
|
@@ -167,6 +176,9 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
|
|
|
167
176
|
overflow: hidden;
|
|
168
177
|
text-overflow: ellipsis;
|
|
169
178
|
min-width: 0;
|
|
179
|
+
/* `overflow: hidden` (needed for the ellipsis) makes this line box the
|
|
180
|
+
clip box — give it leading tall enough to contain the descenders. */
|
|
181
|
+
line-height: var(--button-label-line-height);
|
|
170
182
|
}
|
|
171
183
|
|
|
172
184
|
/* Display convention (ADR-0037): block-level by default — a text button used
|
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.'
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
},
|
|
99
99
|
"options": {
|
|
100
100
|
"description": "Programmatic option list. Array of {value, label, disabled?, group?} or grouped {label, options:[…]}. Alternative to declarative <option> / <optgroup> children.",
|
|
101
|
-
"$ref": "common_types.json#/$defs/
|
|
101
|
+
"$ref": "common_types.json#/$defs/DynamicObjectList"
|
|
102
102
|
},
|
|
103
103
|
"placeholder": {
|
|
104
104
|
"description": "Placeholder text in the input when value is empty",
|
|
@@ -85,6 +85,9 @@ props:
|
|
|
85
85
|
or grouped {label, options:[…]}. Alternative to declarative
|
|
86
86
|
<option> / <optgroup> children.
|
|
87
87
|
type: array
|
|
88
|
+
# Rich option objects — same DynamicObjectList mapping fix as command-ui.
|
|
89
|
+
items:
|
|
90
|
+
type: object
|
|
88
91
|
default: []
|
|
89
92
|
dynamic: true # JS-set collection prop with a custom setter — deliberately not in static properties
|
|
90
93
|
open:
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"type": "boolean",
|
|
22
22
|
"default": false
|
|
23
23
|
},
|
|
24
|
+
"options": {
|
|
25
|
+
"description": "Programmatic item list. Array of {value, label, icon?, shortcut?, disabled?} or grouped {label, options:[…]}. `icon` renders as a leading icon-ui, `shortcut` as a trailing keyboard-shortcut hint — the same fields as the data-icon/data-shortcut attributes on declarative <option> children. Alternative to declarative <option data-icon data-shortcut> / <optgroup label> children.",
|
|
26
|
+
"$ref": "common_types.json#/$defs/DynamicObjectList"
|
|
27
|
+
},
|
|
24
28
|
"placeholder": {
|
|
25
29
|
"description": "Placeholder text for the search input",
|
|
26
30
|
"type": "string",
|
|
@@ -85,10 +85,15 @@ export class UICommand extends UIElement {
|
|
|
85
85
|
render() {
|
|
86
86
|
// Stamp internal structure once
|
|
87
87
|
if (!this.#inputEl) {
|
|
88
|
-
// Parse
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
|
|
88
|
+
// Parse declarative <option>/<optgroup> children once, unless
|
|
89
|
+
// `.options` was already set programmatically before first render
|
|
90
|
+
// (mirrors combobox-ui's connected()-time guard) + capture
|
|
91
|
+
// author-provided slot="empty" content before replacing innerHTML
|
|
92
|
+
// (dogfood-status yaml-drift finding: yaml documented an overridable
|
|
93
|
+
// empty state that was never wired).
|
|
94
|
+
if (this.#items.length === 0) {
|
|
95
|
+
this.#parseOptions();
|
|
96
|
+
}
|
|
92
97
|
this.#emptyNodes = logicalSlotted(this, 'empty');
|
|
93
98
|
|
|
94
99
|
this.innerHTML = `
|
|
@@ -143,6 +148,51 @@ export class UICommand extends UIElement {
|
|
|
143
148
|
this.#renderItems();
|
|
144
149
|
}
|
|
145
150
|
|
|
151
|
+
// ── Programmatic options (gh#887) ──
|
|
152
|
+
//
|
|
153
|
+
// Public API mirroring combobox-ui's `options` prop: an array of flat
|
|
154
|
+
// {value, label, icon?, shortcut?, disabled?} entries, or grouped
|
|
155
|
+
// {label, options:[…]} entries — same field names as the data-icon/
|
|
156
|
+
// data-shortcut attributes on declarative <option> children. Normalized
|
|
157
|
+
// into the internal #items shape #renderItems() already consumes (flat
|
|
158
|
+
// items carry `category`; groups carry `.items` not `.options`), so
|
|
159
|
+
// programmatic and declarative authoring render identically.
|
|
160
|
+
|
|
161
|
+
set options(list) {
|
|
162
|
+
this.#items = this.#normalizeOptions(Array.isArray(list) ? list : []);
|
|
163
|
+
// Only re-render if the internal list has already been stamped —
|
|
164
|
+
// otherwise the pending #items feed the first render() pass directly.
|
|
165
|
+
if (this.#listEl) this.#renderItems(this.#inputEl?.value || '');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
get options() { return this.#items; }
|
|
169
|
+
|
|
170
|
+
#normalizeOptions(list) {
|
|
171
|
+
const out = [];
|
|
172
|
+
for (const entry of list) {
|
|
173
|
+
if (entry && Array.isArray(entry.options)) {
|
|
174
|
+
const label = entry.label || '';
|
|
175
|
+
out.push({ label, items: entry.options.map((opt) => this.#optionObjectToItem(opt, label)) });
|
|
176
|
+
} else if (entry) {
|
|
177
|
+
out.push(this.#optionObjectToItem(entry, ''));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Plain-object counterpart of #optionToItem (which reads a DOM <option>). */
|
|
184
|
+
#optionObjectToItem(opt, category = '') {
|
|
185
|
+
return {
|
|
186
|
+
value: opt.value,
|
|
187
|
+
label: opt.label ?? opt.value,
|
|
188
|
+
icon: opt.icon || '',
|
|
189
|
+
shortcut: opt.shortcut || '',
|
|
190
|
+
keywords: opt.keywords || '',
|
|
191
|
+
disabled: !!opt.disabled,
|
|
192
|
+
category,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
146
196
|
// ── Parse declarative <option>/<optgroup> ──
|
|
147
197
|
|
|
148
198
|
// Wrapper-piercing walk for consumer-authored <option>/<optgroup> children.
|
|
@@ -35,6 +35,8 @@ export type CommandSelectEvent = CustomEvent<CommandSelectEventDetail>;
|
|
|
35
35
|
export class UICommand extends UIElement {
|
|
36
36
|
/** Whether the command palette is visible */
|
|
37
37
|
open: boolean;
|
|
38
|
+
/** Programmatic item list. Array of {value, label, icon?, shortcut?, disabled?} or grouped {label, options:[…]}. `icon` renders as a leading icon-ui, `shortcut` as a trailing keyboard-shortcut hint — the same fields as the data-icon/data-shortcut attributes on declarative <option> children. Alternative to declarative <option data-icon data-shortcut> / <optgroup label> children. */
|
|
39
|
+
options: string;
|
|
38
40
|
/** Placeholder text for the search input */
|
|
39
41
|
placeholder: string;
|
|
40
42
|
|
|
@@ -24,6 +24,24 @@ props:
|
|
|
24
24
|
description: Placeholder text for the search input
|
|
25
25
|
type: string
|
|
26
26
|
default: Type a command...
|
|
27
|
+
options:
|
|
28
|
+
description: >-
|
|
29
|
+
Programmatic item list. Array of {value, label, icon?, shortcut?,
|
|
30
|
+
disabled?} or grouped {label, options:[…]}. `icon` renders as a
|
|
31
|
+
leading icon-ui, `shortcut` as a trailing keyboard-shortcut hint —
|
|
32
|
+
the same fields as the data-icon/data-shortcut attributes on
|
|
33
|
+
declarative <option> children. Alternative to declarative
|
|
34
|
+
<option data-icon data-shortcut> / <optgroup label> children.
|
|
35
|
+
type: array
|
|
36
|
+
# Rich option OBJECTS ({value, label, icon?, …} / grouped) — declares
|
|
37
|
+
# items.type so the a2ui catalog maps to DynamicObjectList, not the
|
|
38
|
+
# string-list default (components.mjs TKT-0010 mapping). Without this
|
|
39
|
+
# the dialect validator rejected every harvested rich-options palette
|
|
40
|
+
# (exit-gate.corpus caught it at release pre-flight).
|
|
41
|
+
items:
|
|
42
|
+
type: object
|
|
43
|
+
default: []
|
|
44
|
+
dynamic: true # JS-set collection prop with a custom setter — mirrors combobox-ui's `options`
|
|
27
45
|
events:
|
|
28
46
|
dismiss:
|
|
29
47
|
description: Fired when Escape is pressed
|
|
@@ -69,9 +87,13 @@ a2ui:
|
|
|
69
87
|
shortcut. Do NOT hand-roll a <dialog> + Cmd+K key listener.
|
|
70
88
|
- >-
|
|
71
89
|
Author items as native <option value data-icon data-shortcut>
|
|
72
|
-
elements inside <optgroup label="…"> for grouped sections
|
|
73
|
-
`
|
|
74
|
-
|
|
90
|
+
elements inside <optgroup label="…"> for grouped sections, OR set
|
|
91
|
+
`.options` programmatically as an array of
|
|
92
|
+
`{value, label, icon?, shortcut?, disabled?}` (grouped form:
|
|
93
|
+
`{label, options:[…]}`) — same fields, alternative to declarative
|
|
94
|
+
children. The `select` event's detail.category mirrors the parent
|
|
95
|
+
optgroup's label (or the group's `label` when authored via
|
|
96
|
+
`options`). Detail = { value, label, category }.
|
|
75
97
|
- >-
|
|
76
98
|
Decision rule vs adjacent surfaces. Use <menu-ui> for small
|
|
77
99
|
NON-searchable popover menus (≤10 actions, triggered by a
|
|
@@ -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/DateRangePicker.json",
|
|
4
4
|
"title": "DateRangePicker",
|
|
5
|
-
"description": "Compound form primitive for selecting a start + end date pair with optional named preset shortcuts (\"Today\", \"Last 7 days\", \"This month\", ...). Default presentation is a trigger button showing the formatted range; on activation a popover opens with two synchronized calendar panes + a preset side rail. Composes <calendar-
|
|
5
|
+
"description": "Compound form primitive for selecting a start + end date pair with optional named preset shortcuts (\"Today\", \"Last 7 days\", \"This month\", ...). Default presentation is a trigger button showing the formatted range; on activation a popover opens with two synchronized calendar panes + a preset side rail. Composes <calendar-grid-ui> twice; emits {from, to} ISO 8601 dates. Both panes are ONE selection surface: first click = start, second click = end, in either grid; a second click earlier than the start restarts the range there. Optional comparison-range mode emits a secondary range for analytics surfaces.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"allOf": [
|
|
8
8
|
{
|