@adia-ai/web-components 0.8.30 → 0.8.32
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 +59 -0
- package/components/accordion/accordion.d.ts +2 -2
- package/components/action-list/action-list.class.js +6 -2
- package/components/action-list/action-list.d.ts +1 -1
- package/components/agent-artifact/agent-artifact.d.ts +1 -1
- package/components/agent-feedback-bar/agent-feedback-bar.d.ts +2 -2
- package/components/agent-questions/agent-questions.d.ts +1 -1
- package/components/agent-reasoning/agent-reasoning.d.ts +3 -3
- package/components/agent-suggestions/agent-suggestions.d.ts +1 -1
- package/components/agent-trace/agent-trace.d.ts +1 -1
- package/components/alert/alert.d.ts +2 -2
- package/components/anchor-bar/anchor-bar.d.ts +2 -2
- package/components/avatar/avatar.class.js +0 -1
- package/components/avatar/avatar.css +16 -2
- package/components/badge/badge.css +30 -2
- package/components/breadcrumb/breadcrumb.css +15 -3
- package/components/button/button.d.ts +1 -1
- package/components/calendar-grid/calendar-grid.d.ts +2 -2
- package/components/card/card.css +21 -0
- package/components/card/card.yaml +9 -0
- package/components/chart/chart.d.ts +4 -4
- package/components/chart-legend/chart-legend.d.ts +1 -1
- package/components/chat-thread/chat-input.css +1 -1
- package/components/chat-thread/chat-input.js +9 -1
- package/components/chat-thread/chat-thread.class.js +6 -0
- package/components/chat-thread/chat-thread.d.ts +2 -2
- package/components/check/check.css +3 -3
- package/components/command/command.d.ts +2 -2
- package/components/context-menu/context-menu.d.ts +3 -3
- package/components/datetime-picker/datetime-picker.d.ts +5 -5
- package/components/demo-toggle/demo-toggle.d.ts +1 -1
- package/components/drawer/drawer.d.ts +2 -2
- package/components/heatmap/heatmap.d.ts +5 -5
- package/components/index.js +1 -0
- package/components/inline-edit/inline-edit.d.ts +4 -4
- package/components/input/input.a2ui.json +4 -1
- package/components/input/input.css +18 -0
- package/components/input/input.yaml +11 -1
- package/components/integration-card/integration-card.d.ts +4 -4
- package/components/link/link.d.ts +1 -1
- package/components/list/list-item.a2ui.json +6 -0
- package/components/list/list-item.yaml +13 -0
- package/components/list/list.class.js +28 -7
- package/components/list/list.d.ts +1 -1
- package/components/list-window/list-window.d.ts +5 -5
- package/components/menu/menu.css +2 -2
- package/components/menu/menu.d.ts +1 -1
- package/components/modal/modal.d.ts +1 -1
- package/components/nav/nav.css +8 -0
- package/components/nav/nav.d.ts +1 -1
- package/components/nav-group/nav-group.css +58 -9
- package/components/nav-group/nav-group.d.ts +1 -1
- package/components/nav-item/nav-item.css +7 -4
- package/components/nav-item/nav-item.d.ts +1 -1
- package/components/noodles/noodles.d.ts +3 -3
- package/components/option-card/option-card.css +1 -1
- package/components/pagination/pagination.d.ts +1 -1
- package/components/pane/pane.d.ts +1 -1
- package/components/password-strength/password-strength.d.ts +1 -1
- package/components/pipeline-status/pipeline-status.a2ui.json +14 -8
- package/components/pipeline-status/pipeline-status.d.ts +5 -4
- package/components/pipeline-status/pipeline-status.yaml +17 -11
- package/components/radio/radio.a2ui.json +4 -3
- package/components/radio/radio.css +2 -2
- package/components/radio/radio.yaml +7 -14
- package/components/radio-group/radio-group.a2ui.json +118 -0
- package/components/radio-group/radio-group.class.js +75 -0
- package/components/radio-group/radio-group.css +31 -0
- package/components/radio-group/radio-group.d.ts +20 -0
- package/components/radio-group/radio-group.examples.md +37 -0
- package/components/radio-group/radio-group.js +17 -0
- package/components/radio-group/radio-group.yaml +114 -0
- package/components/segmented/segmented.a2ui.json +5 -0
- package/components/segmented/segmented.class.js +20 -2
- package/components/segmented/segmented.yaml +5 -0
- package/components/stat/stat.css +12 -8
- package/components/stat/stat.js +66 -1
- package/components/stat/stat.yaml +3 -0
- package/components/stepper/stepper-item.a2ui.json +5 -0
- package/components/stepper/stepper-item.yaml +11 -0
- package/components/stepper/stepper.a2ui.json +38 -3
- package/components/stepper/stepper.class.js +199 -2
- package/components/stepper/stepper.css +30 -0
- package/components/stepper/stepper.d.ts +28 -1
- package/components/stepper/stepper.yaml +76 -2
- package/components/stream/stream.d.ts +3 -3
- package/components/swatch/swatch.class.js +1 -1
- package/components/swatch/swatch.d.ts +1 -1
- package/components/swiper/swiper.d.ts +3 -3
- package/components/table/table.a2ui.json +2 -2
- package/components/table/table.d.ts +7 -7
- package/components/table/table.yaml +9 -1
- package/components/table-toolbar/table-toolbar.d.ts +4 -4
- package/components/tabs/tabs.css +11 -3
- package/components/tabs/tabs.d.ts +1 -1
- package/components/tag/tag.a2ui.json +1 -1
- package/components/tag/tag.css +78 -13
- package/components/tag/tag.d.ts +12 -8
- package/components/tag/tag.examples.md +4 -4
- package/components/tag/tag.yaml +18 -7
- package/components/tags-input/tags-input.d.ts +4 -4
- package/components/timeline/timeline.d.ts +1 -1
- package/components/toc/toc.d.ts +1 -1
- package/components/toggle-group/toggle-group.d.ts +1 -1
- package/components/toggle-scheme/toggle-scheme.d.ts +1 -1
- package/components/tour/tour.d.ts +4 -4
- package/components/tree/tree.d.ts +1 -1
- package/core/icons-phosphor.js +129 -71
- package/core/provider.js +84 -23
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +1 -1
- package/dist/theme-provider.min.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +89 -87
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -1
- package/styles/api/sizing-fallback.css +32 -0
- package/styles/api/sizing.css +7 -3
- package/styles/components.css +1 -0
- package/styles/tokens.css +1 -0
|
@@ -28,21 +28,104 @@
|
|
|
28
28
|
*
|
|
29
29
|
* el.next(); el.prev(); el.goTo(2);
|
|
30
30
|
*
|
|
31
|
+
* <!-- Host-controlled click-to-navigate + keyboard (gh#711 S1) -->
|
|
32
|
+
* <stepper-ui step="1" interactive>
|
|
33
|
+
* <stepper-item-ui text="Account"></stepper-item-ui>
|
|
34
|
+
* <stepper-item-ui text="Details" disabled></stepper-item-ui>
|
|
35
|
+
* ...
|
|
36
|
+
* </stepper-ui>
|
|
37
|
+
*
|
|
38
|
+
* <!-- Veto a navigation before it lands (gh#711 S1 review) -->
|
|
39
|
+
* el.addEventListener('step-request', (e) => {
|
|
40
|
+
* if (!phaseAllows(e.detail.step)) e.preventDefault();
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
31
43
|
* Attributes:
|
|
32
44
|
* step — current step index (0-based)
|
|
33
45
|
* orientation — horizontal (default) | vertical
|
|
46
|
+
* interactive — opt-in click-to-navigate + roving-tabindex keyboard
|
|
47
|
+
* nav (arrow keys / Home / End). Absent by default —
|
|
48
|
+
* a bare stepper is a read-only progress display.
|
|
49
|
+
*
|
|
50
|
+
* Events (interactive only):
|
|
51
|
+
* step-request — cancelable, fires BEFORE `step` mutates.
|
|
52
|
+
* { detail: { step, previous } }. `preventDefault()`
|
|
53
|
+
* vetoes the navigation: no mutation, no `change`,
|
|
54
|
+
* focus/roving state unaffected. A host that never
|
|
55
|
+
* listens keeps today's uncontrolled behavior —
|
|
56
|
+
* this is additive, not a breaking change.
|
|
57
|
+
* change — { detail: { step } } — fires AFTER a click or
|
|
58
|
+
* keyboard navigation changes `step` (i.e. only if
|
|
59
|
+
* `step-request` wasn't vetoed). The host reacts;
|
|
60
|
+
* the stepper does not itself drive any other UI.
|
|
34
61
|
*/
|
|
35
62
|
|
|
36
63
|
import { UIElement } from '../../core/element.js';
|
|
37
64
|
|
|
65
|
+
// gh#736 — during static innerHTML parsing, a stepper-item-ui's attribute
|
|
66
|
+
// list is on the DOM node the instant the parser inserts it, but its
|
|
67
|
+
// `disabled` PROPERTY mirror only lands once its own attributeChangedCallback
|
|
68
|
+
// replay has run — which some environments (this repo's happy-dom test env,
|
|
69
|
+
// certain upgrade orderings) don't guarantee has happened yet by the time the
|
|
70
|
+
// PARENT's connectedCallback (and its first render()) fires, since children
|
|
71
|
+
// connect after their parent in tree order. Reading the attribute directly
|
|
72
|
+
// is synchronous with parsing and never lags, so it's the race-proof source
|
|
73
|
+
// of truth; the property read stays primary for the (overwhelmingly common)
|
|
74
|
+
// already-upgraded case.
|
|
75
|
+
function isDisabled(item) {
|
|
76
|
+
return item.disabled || item.hasAttribute('disabled');
|
|
77
|
+
}
|
|
78
|
+
|
|
38
79
|
export class UIStepper extends UIElement {
|
|
39
80
|
static properties = {
|
|
40
|
-
step: { type: Number,
|
|
41
|
-
orientation: { type: String,
|
|
81
|
+
step: { type: Number, default: 0, reflect: true },
|
|
82
|
+
orientation: { type: String, default: 'horizontal', reflect: true },
|
|
83
|
+
interactive: { type: Boolean, default: false, reflect: true },
|
|
42
84
|
};
|
|
43
85
|
|
|
44
86
|
static template = () => null;
|
|
45
87
|
|
|
88
|
+
// gh#736 — two related child-reactivity gaps, one observer:
|
|
89
|
+
// 1. Upgrade-order race: during static innerHTML parsing this element's
|
|
90
|
+
// connectedCallback (and its first synchronous render()) can fire
|
|
91
|
+
// BEFORE its stepper-item-ui children are even appended as DOM
|
|
92
|
+
// children (confirmed: this element's own render() sees zero items
|
|
93
|
+
// on that first pass) — the isDisabled() hasAttribute fallback in
|
|
94
|
+
// render() alone can't help when there's nothing to iterate yet.
|
|
95
|
+
// Watching `childList` catches children landing a tick later and
|
|
96
|
+
// re-renders once they're actually there.
|
|
97
|
+
// 2. A child's [disabled] flip after mount must re-render this parent's
|
|
98
|
+
// roving-tabindex/aria-disabled computation without the host
|
|
99
|
+
// manually poking render() (nav-group-ui's gh#501 idiom: a scoped
|
|
100
|
+
// MutationObserver, not a signal, since `disabled` lives on
|
|
101
|
+
// descendant DOM, not this element's own reactive properties).
|
|
102
|
+
// attributeFilter is narrow (['disabled']) and render() never writes
|
|
103
|
+
// childList or that attribute itself (it only reads `disabled`), so the
|
|
104
|
+
// observer can't feed back into its own render.
|
|
105
|
+
#onChildMutation = () => this.render();
|
|
106
|
+
#childObserver = null;
|
|
107
|
+
|
|
108
|
+
connected() {
|
|
109
|
+
this.addEventListener('click', this.#handleClick);
|
|
110
|
+
this.addEventListener('keydown', this.#handleKeydown);
|
|
111
|
+
if (!this.#childObserver) {
|
|
112
|
+
this.#childObserver = new MutationObserver(this.#onChildMutation);
|
|
113
|
+
this.#childObserver.observe(this, {
|
|
114
|
+
childList: true,
|
|
115
|
+
subtree: true,
|
|
116
|
+
attributes: true,
|
|
117
|
+
attributeFilter: ['disabled'],
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
disconnected() {
|
|
123
|
+
this.removeEventListener('click', this.#handleClick);
|
|
124
|
+
this.removeEventListener('keydown', this.#handleKeydown);
|
|
125
|
+
this.#childObserver?.disconnect();
|
|
126
|
+
this.#childObserver = null;
|
|
127
|
+
}
|
|
128
|
+
|
|
46
129
|
render() {
|
|
47
130
|
const items = [...this.querySelectorAll('stepper-item-ui')];
|
|
48
131
|
|
|
@@ -64,7 +147,40 @@ export class UIStepper extends UIElement {
|
|
|
64
147
|
} else {
|
|
65
148
|
item.setAttribute('status', 'idle');
|
|
66
149
|
}
|
|
150
|
+
|
|
151
|
+
// Roving tabindex + button semantics only when the host opts
|
|
152
|
+
// in via [interactive] — a bare stepper stays a non-focusable
|
|
153
|
+
// progress display (Rule: absent attribute is the default).
|
|
154
|
+
if (this.interactive) {
|
|
155
|
+
item.setAttribute('role', 'button');
|
|
156
|
+
if (i === this.step) item.setAttribute('aria-current', 'step');
|
|
157
|
+
else item.removeAttribute('aria-current');
|
|
158
|
+
} else {
|
|
159
|
+
item.removeAttribute('role');
|
|
160
|
+
item.removeAttribute('tabindex');
|
|
161
|
+
item.removeAttribute('aria-current');
|
|
162
|
+
item.removeAttribute('aria-disabled');
|
|
163
|
+
}
|
|
67
164
|
});
|
|
165
|
+
|
|
166
|
+
// Disabled items (S2's phase-gating mechanism) never take the
|
|
167
|
+
// roving tabindex stop and are never clickable/keyboard-reachable
|
|
168
|
+
// — an author-set [disabled] on a stepper-item-ui always wins,
|
|
169
|
+
// whatever [status] the parent computed for it above.
|
|
170
|
+
if (this.interactive) {
|
|
171
|
+
const enabled = items.filter((item) => !isDisabled(item));
|
|
172
|
+
const current = items[this.step];
|
|
173
|
+
const focusTarget = current && !isDisabled(current) ? current : enabled[0];
|
|
174
|
+
for (const item of items) {
|
|
175
|
+
if (isDisabled(item)) {
|
|
176
|
+
item.setAttribute('aria-disabled', 'true');
|
|
177
|
+
item.removeAttribute('tabindex');
|
|
178
|
+
} else {
|
|
179
|
+
item.removeAttribute('aria-disabled');
|
|
180
|
+
item.setAttribute('tabindex', item === focusTarget ? '0' : '-1');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
68
184
|
}
|
|
69
185
|
|
|
70
186
|
next() {
|
|
@@ -80,6 +196,82 @@ export class UIStepper extends UIElement {
|
|
|
80
196
|
const max = this.querySelectorAll('stepper-item-ui').length - 1;
|
|
81
197
|
this.step = Math.max(0, Math.min(index, max));
|
|
82
198
|
}
|
|
199
|
+
|
|
200
|
+
get #items() {
|
|
201
|
+
return [...this.querySelectorAll('stepper-item-ui')];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
get #enabledItems() {
|
|
205
|
+
return this.#items.filter((item) => !isDisabled(item));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** @returns {boolean} true if the navigation landed, false if vetoed or a no-op. */
|
|
209
|
+
#select(index) {
|
|
210
|
+
const items = this.#items;
|
|
211
|
+
const max = items.length - 1;
|
|
212
|
+
const next = Math.max(0, Math.min(index, max));
|
|
213
|
+
if (next === this.step || (items[next] && isDisabled(items[next]))) return false;
|
|
214
|
+
|
|
215
|
+
// Pre-mutation cancelable event (gh#711 S1 review) — the host
|
|
216
|
+
// gets a veto BEFORE `step` changes. `preventDefault()` stops
|
|
217
|
+
// the mutation and the `change` event; focus/roving are
|
|
218
|
+
// untouched either way. A host that never listens sees no
|
|
219
|
+
// difference from before this event existed.
|
|
220
|
+
const previous = this.step;
|
|
221
|
+
const proceed = this.dispatchEvent(new CustomEvent('step-request', {
|
|
222
|
+
bubbles: true,
|
|
223
|
+
cancelable: true,
|
|
224
|
+
detail: { step: next, previous },
|
|
225
|
+
}));
|
|
226
|
+
if (!proceed) return false; // vetoed
|
|
227
|
+
|
|
228
|
+
this.step = next;
|
|
229
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true, detail: { step: this.step } }));
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
#handleClick = (e) => {
|
|
234
|
+
if (!this.interactive) return;
|
|
235
|
+
const item = e.target.closest('stepper-item-ui');
|
|
236
|
+
if (!item || !this.contains(item) || isDisabled(item)) return;
|
|
237
|
+
const index = this.#items.indexOf(item);
|
|
238
|
+
if (index < 0) return;
|
|
239
|
+
this.#select(index);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
#handleKeydown = (e) => {
|
|
243
|
+
if (!this.interactive) return;
|
|
244
|
+
const item = e.target.closest('stepper-item-ui');
|
|
245
|
+
if (!item || !this.contains(item)) return;
|
|
246
|
+
|
|
247
|
+
// Disabled items are unreachable (no tabindex) and skipped in the
|
|
248
|
+
// arrow/Home/End order — the roving set is the enabled subset.
|
|
249
|
+
const items = this.#enabledItems;
|
|
250
|
+
const idx = items.indexOf(item);
|
|
251
|
+
if (idx < 0) return;
|
|
252
|
+
|
|
253
|
+
const isVertical = this.orientation === 'vertical';
|
|
254
|
+
const nextKey = isVertical ? 'ArrowDown' : 'ArrowRight';
|
|
255
|
+
const prevKey = isVertical ? 'ArrowUp' : 'ArrowLeft';
|
|
256
|
+
|
|
257
|
+
let next;
|
|
258
|
+
switch (e.key) {
|
|
259
|
+
case nextKey: next = idx < items.length - 1 ? idx + 1 : 0; break; // wraps to first
|
|
260
|
+
case prevKey: next = idx > 0 ? idx - 1 : items.length - 1; break; // wraps to last
|
|
261
|
+
case 'Home': next = 0; break;
|
|
262
|
+
case 'End': next = items.length - 1; break;
|
|
263
|
+
case 'Enter':
|
|
264
|
+
case ' ': e.preventDefault(); this.#select(this.#items.indexOf(item)); return;
|
|
265
|
+
default: return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
e.preventDefault();
|
|
269
|
+
const target = items[next];
|
|
270
|
+
// Only move roving focus if the navigation actually landed — a
|
|
271
|
+
// veto leaves focus (and the tabindex roving stop) exactly where
|
|
272
|
+
// it was, per the review's "focus/roving unaffected" contract.
|
|
273
|
+
if (this.#select(this.#items.indexOf(target))) target.focus();
|
|
274
|
+
};
|
|
83
275
|
}
|
|
84
276
|
|
|
85
277
|
export class UIStepperItem extends UIElement {
|
|
@@ -92,6 +284,11 @@ export class UIStepperItem extends UIElement {
|
|
|
92
284
|
// values prevent the `active && completed` footgun the prior multi-
|
|
93
285
|
// Boolean shape allowed.
|
|
94
286
|
status: { type: String, default: 'idle', reflect: true },
|
|
287
|
+
// S2's phase-gating mechanism (gh#711 S1 review) — a disabled step
|
|
288
|
+
// is skipped in [interactive] roving tabindex/arrow order, is
|
|
289
|
+
// unclickable, and carries aria-disabled. Independent of `status`:
|
|
290
|
+
// a completed or upcoming step can be disabled for a different reason.
|
|
291
|
+
disabled: { type: Boolean, default: false, reflect: true },
|
|
95
292
|
};
|
|
96
293
|
|
|
97
294
|
static template = () => null;
|
|
@@ -253,6 +253,36 @@
|
|
|
253
253
|
:scope [slot]:empty {
|
|
254
254
|
display: none;
|
|
255
255
|
}
|
|
256
|
+
|
|
257
|
+
/* Interactive (click-to-navigate) — host opts in via [interactive]
|
|
258
|
+
on the parent; absent by default (Rule: bare stepper is a
|
|
259
|
+
read-only progress display, not a nav control). */
|
|
260
|
+
stepper-ui[interactive] > :scope {
|
|
261
|
+
cursor: pointer;
|
|
262
|
+
outline: none;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
stepper-ui[interactive] > :scope:focus-visible::after {
|
|
266
|
+
outline: 2px solid var(--md-sys-color-primary);
|
|
267
|
+
outline-offset: 2px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* Disabled (S2's phase-gating mechanism) — never clickable, never
|
|
271
|
+
the roving-tabindex stop; visually recedes regardless of status. */
|
|
272
|
+
stepper-ui[interactive] > :scope[disabled] {
|
|
273
|
+
cursor: not-allowed;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
:scope[disabled]::after,
|
|
277
|
+
:scope[disabled] [slot="icon"] {
|
|
278
|
+
opacity: 0.5;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
:scope[disabled] [slot="label"],
|
|
282
|
+
:scope[disabled] [slot="description"] {
|
|
283
|
+
color: var(--stepper-item-pending-fg);
|
|
284
|
+
opacity: 0.5;
|
|
285
|
+
}
|
|
256
286
|
}
|
|
257
287
|
|
|
258
288
|
/* ── Vertical orientation rules — must reach across stepper-ui →
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `<stepper-ui>` — Wizard / process stepper — parent step index drives numbered children's complete/current/upcoming states automatically. Renders horizontally as a labeled step bar with connectors. Use for multi-step forms, onboarding, or pipelines; for read-only event history use <timeline-ui> instead.
|
|
2
|
+
* `<stepper-ui>` — Wizard / process stepper — parent step index drives numbered children's complete/current/upcoming states automatically. Renders horizontally as a labeled step bar with connectors. Use for multi-step forms, onboarding, or pipelines; for read-only event history use <timeline-ui> instead. Add [interactive] to opt into click-to-navigate + roving- tabindex keyboard (arrow keys / Home / End) — the host still owns whether navigation is permitted: listen for the cancelable [step-request] event and call preventDefault() to veto a step before it lands, or set [disabled] on a stepper-item-ui to phase-gate it out of reach entirely.
|
|
3
3
|
*
|
|
4
4
|
* @see https://ui-kit.exe.xyz/site/components/stepper
|
|
5
5
|
*
|
|
@@ -12,16 +12,43 @@
|
|
|
12
12
|
|
|
13
13
|
import { UIElement } from '../../core/element.js';
|
|
14
14
|
|
|
15
|
+
export interface StepperChangeEventDetail {
|
|
16
|
+
/** New current step index. */
|
|
17
|
+
step: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type StepperChangeEvent = CustomEvent<StepperChangeEventDetail>;
|
|
21
|
+
export interface StepperStepRequestEventDetail {
|
|
22
|
+
/** The current step index before this navigation. */
|
|
23
|
+
previous: number;
|
|
24
|
+
/** The step index the navigation would land on if not vetoed. */
|
|
25
|
+
step: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type StepperStepRequestEvent = CustomEvent<StepperStepRequestEventDetail>;
|
|
29
|
+
|
|
15
30
|
export class UIStepper extends UIElement {
|
|
31
|
+
/** Opt into click-to-navigate + roving-tabindex keyboard nav (arrow keys / Home / End / Enter / Space). Absent by default — a bare stepper is a read-only progress display, not a nav control (gh#711 S1). */
|
|
32
|
+
interactive: boolean;
|
|
16
33
|
/** horizontal | vertical */
|
|
17
34
|
orientation: string;
|
|
18
35
|
/** Current step index (0-based). */
|
|
19
36
|
step: number;
|
|
37
|
+
|
|
38
|
+
addEventListener(type: 'change', listener: (ev: StepperChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
39
|
+
addEventListener(type: 'step-request', listener: (ev: StepperStepRequestEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
40
|
+
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
41
|
+
type: K,
|
|
42
|
+
listener: (this: UIStepper, ev: HTMLElementEventMap[K]) => unknown,
|
|
43
|
+
options?: boolean | AddEventListenerOptions,
|
|
44
|
+
): void;
|
|
20
45
|
}
|
|
21
46
|
|
|
22
47
|
export class UIStepperItem extends UIElement {
|
|
23
48
|
/** Secondary description line under the label. */
|
|
24
49
|
description: string;
|
|
50
|
+
/** S2's phase-gating mechanism (gh#711 S1 review). Skipped in the parent's [interactive] roving tabindex/arrow order, unclickable, carries aria-disabled. Independent of [status] — a completed or upcoming step can still be disabled for a different reason (e.g. the visit phase hasn't unlocked it yet). */
|
|
51
|
+
disabled: boolean;
|
|
25
52
|
/** Optional leading Phosphor icon name; overrides the auto-stamped numeric badge. */
|
|
26
53
|
icon: string;
|
|
27
54
|
/** Canonical stage-progress state. Mutually exclusive (prevents the
|
|
@@ -12,7 +12,12 @@ description: >-
|
|
|
12
12
|
complete/current/upcoming states automatically. Renders horizontally as
|
|
13
13
|
a labeled step bar with connectors. Use for multi-step forms,
|
|
14
14
|
onboarding, or pipelines; for read-only event history use <timeline-ui>
|
|
15
|
-
instead.
|
|
15
|
+
instead. Add [interactive] to opt into click-to-navigate + roving-
|
|
16
|
+
tabindex keyboard (arrow keys / Home / End) — the host still owns
|
|
17
|
+
whether navigation is permitted: listen for the cancelable
|
|
18
|
+
[step-request] event and call preventDefault() to veto a step before
|
|
19
|
+
it lands, or set [disabled] on a stepper-item-ui to phase-gate it
|
|
20
|
+
out of reach entirely.
|
|
16
21
|
# Per ADR-0027 — primitives that programmatically create other primitives
|
|
17
22
|
# do NOT auto-import them. Consumer (or demo shell) must explicitly import.
|
|
18
23
|
composes:
|
|
@@ -26,7 +31,39 @@ props:
|
|
|
26
31
|
description: Current step index (0-based).
|
|
27
32
|
type: number
|
|
28
33
|
default: 0
|
|
29
|
-
|
|
34
|
+
interactive:
|
|
35
|
+
description: >-
|
|
36
|
+
Opt into click-to-navigate + roving-tabindex keyboard nav
|
|
37
|
+
(arrow keys / Home / End / Enter / Space). Absent by default —
|
|
38
|
+
a bare stepper is a read-only progress display, not a nav
|
|
39
|
+
control (gh#711 S1).
|
|
40
|
+
type: boolean
|
|
41
|
+
default: false
|
|
42
|
+
events:
|
|
43
|
+
step-request:
|
|
44
|
+
description: >-
|
|
45
|
+
Cancelable — fires BEFORE [step] mutates, on a click or keyboard
|
|
46
|
+
navigation. call preventDefault() to veto: the step does not
|
|
47
|
+
change, [change] does not fire, and focus/roving-tabindex stay
|
|
48
|
+
exactly where they were. A host that never listens for this
|
|
49
|
+
event keeps the pre-veto uncontrolled behavior unchanged
|
|
50
|
+
(gh#711 S1 review).
|
|
51
|
+
detail:
|
|
52
|
+
step:
|
|
53
|
+
type: number
|
|
54
|
+
description: The step index the navigation would land on if not vetoed.
|
|
55
|
+
previous:
|
|
56
|
+
type: number
|
|
57
|
+
description: The current step index before this navigation.
|
|
58
|
+
change:
|
|
59
|
+
description: >-
|
|
60
|
+
Fired after a click or keyboard navigation changes [step] (i.e.
|
|
61
|
+
only when the preceding [step-request] wasn't vetoed).
|
|
62
|
+
Only fires when [interactive] is set.
|
|
63
|
+
detail:
|
|
64
|
+
step:
|
|
65
|
+
type: number
|
|
66
|
+
description: New current step index.
|
|
30
67
|
slots:
|
|
31
68
|
default:
|
|
32
69
|
description: "Default slot — primary child content."
|
|
@@ -43,6 +80,10 @@ a2ui:
|
|
|
43
80
|
reason: 'Surface examples.'
|
|
44
81
|
- rule: 'For read-only event history use <timeline-ui>; stepper requires forward progress semantics.'
|
|
45
82
|
reason: 'Decision rule vs timeline.'
|
|
83
|
+
- rule: 'Add [interactive] only when the host permits jumping to a step out of order; leave absent for a linear wizard the host advances programmatically.'
|
|
84
|
+
reason: 'Click-to-navigate is host-controlled, not automatic (gh#711 S1).'
|
|
85
|
+
- rule: 'Listen for [step-request] and call preventDefault() to veto a navigation conditionally (e.g. block a phase the app has not unlocked); set [disabled] on a stepper-item-ui to phase-gate it out of reach unconditionally.'
|
|
86
|
+
reason: 'Two host-controlled gates at different granularities (gh#711 S1 review).'
|
|
46
87
|
anti_patterns: []
|
|
47
88
|
examples:
|
|
48
89
|
- name: basic
|
|
@@ -75,6 +116,37 @@ examples:
|
|
|
75
116
|
"text": "Review"
|
|
76
117
|
}
|
|
77
118
|
]
|
|
119
|
+
- name: interactive
|
|
120
|
+
description: Click/keyboard-navigable stepper — host allows jumping between steps.
|
|
121
|
+
a2ui: >-
|
|
122
|
+
[
|
|
123
|
+
{
|
|
124
|
+
"id": "root",
|
|
125
|
+
"component": "Stepper",
|
|
126
|
+
"step": 1,
|
|
127
|
+
"interactive": true,
|
|
128
|
+
"children": [
|
|
129
|
+
"s1",
|
|
130
|
+
"s2",
|
|
131
|
+
"s3"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "s1",
|
|
136
|
+
"component": "StepperItem",
|
|
137
|
+
"text": "Account"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "s2",
|
|
141
|
+
"component": "StepperItem",
|
|
142
|
+
"text": "Details"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "s3",
|
|
146
|
+
"component": "StepperItem",
|
|
147
|
+
"text": "Review"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
78
150
|
keywords:
|
|
79
151
|
- stepper
|
|
80
152
|
- wizard
|
|
@@ -82,6 +154,8 @@ keywords:
|
|
|
82
154
|
- process
|
|
83
155
|
- onboarding
|
|
84
156
|
- multi-step
|
|
157
|
+
- interactive
|
|
158
|
+
- click-to-navigate
|
|
85
159
|
synonyms:
|
|
86
160
|
timeline-ui mode=steps: stepper-ui
|
|
87
161
|
related:
|
|
@@ -27,12 +27,12 @@ export class UIStream extends UIElement {
|
|
|
27
27
|
/** Read-only reflected state, true while stream is active */
|
|
28
28
|
streaming: boolean;
|
|
29
29
|
|
|
30
|
+
addEventListener(type: 'stream-end', listener: (ev: StreamEndEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
31
|
+
addEventListener(type: 'stream-error', listener: (ev: StreamErrorEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
32
|
+
addEventListener(type: 'stream-start', listener: (ev: StreamStartEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
30
33
|
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
31
34
|
type: K,
|
|
32
35
|
listener: (this: UIStream, ev: HTMLElementEventMap[K]) => unknown,
|
|
33
36
|
options?: boolean | AddEventListenerOptions,
|
|
34
37
|
): void;
|
|
35
|
-
addEventListener(type: 'stream-end', listener: (ev: StreamEndEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
36
|
-
addEventListener(type: 'stream-error', listener: (ev: StreamErrorEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
37
|
-
addEventListener(type: 'stream-start', listener: (ev: StreamStartEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
38
38
|
}
|
|
@@ -166,7 +166,7 @@ export class UISwatch extends UIElement {
|
|
|
166
166
|
copyValue: { type: String, default: '' }, // not reflected — long color strings as attrs read poorly
|
|
167
167
|
selectable: { type: Boolean, default: false, reflect: true },
|
|
168
168
|
selected: { type: Boolean, default: false, reflect: true },
|
|
169
|
-
autoContrast: { type: Boolean, default: false, reflect: true },
|
|
169
|
+
autoContrast: { type: Boolean, default: false, reflect: true, attribute: 'auto-contrast' },
|
|
170
170
|
// §253 (v0.5.12, FB-23 §1): label position relative to the tile.
|
|
171
171
|
// `below` (default) = current shape="block" stacked layout.
|
|
172
172
|
// `overlay` = label sits ON the tile via absolute positioning;
|
|
@@ -73,10 +73,10 @@ pattern; blocked 3 cycles on this design call). */
|
|
|
73
73
|
/** Size preset — sm / md / lg. Drives the swatch's intrinsic dimensions; lg is reserved for the token-scale demo (40 px tall). */
|
|
74
74
|
size: 'sm' | 'md' | 'lg';
|
|
75
75
|
|
|
76
|
+
addEventListener(type: 'select', listener: (ev: SwatchSelectEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
76
77
|
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
77
78
|
type: K,
|
|
78
79
|
listener: (this: UISwatch, ev: HTMLElementEventMap[K]) => unknown,
|
|
79
80
|
options?: boolean | AddEventListenerOptions,
|
|
80
81
|
): void;
|
|
81
|
-
addEventListener(type: 'select', listener: (ev: SwatchSelectEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
82
82
|
}
|
|
@@ -52,12 +52,12 @@ export class UISwiper extends UIElement {
|
|
|
52
52
|
/** Scroll-snap alignment — start, center, end, or none. */
|
|
53
53
|
snap: 'start' | 'center' | 'end' | 'none';
|
|
54
54
|
|
|
55
|
+
addEventListener(type: 'autoplay-pause', listener: (ev: SwiperAutoplayPauseEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
56
|
+
addEventListener(type: 'autoplay-resume', listener: (ev: SwiperAutoplayResumeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
57
|
+
addEventListener(type: 'change', listener: (ev: SwiperChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
55
58
|
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
56
59
|
type: K,
|
|
57
60
|
listener: (this: UISwiper, ev: HTMLElementEventMap[K]) => unknown,
|
|
58
61
|
options?: boolean | AddEventListenerOptions,
|
|
59
62
|
): void;
|
|
60
|
-
addEventListener(type: 'autoplay-pause', listener: (ev: SwiperAutoplayPauseEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
61
|
-
addEventListener(type: 'autoplay-resume', listener: (ev: SwiperAutoplayResumeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
62
|
-
addEventListener(type: 'change', listener: (ev: SwiperChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
63
63
|
}
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"default": false
|
|
41
41
|
},
|
|
42
42
|
"frameless": {
|
|
43
|
-
"description": "Drop the table's outer 1px perimeter and nothing else (gh#511) — row dividers are untouched (the perimeter is split onto its own --table-perimeter token, defaulting to --table-border). For card-composed tables: the card owns the frame, so the table's square perimeter otherwise renders a doubled edge (flush bleed) or a stray inner box (with content above). Standalone tables keep their chrome by default. Theming path without the attribute: set --table-perimeter to transparent per instance.",
|
|
43
|
+
"description": "Drop the table's outer 1px perimeter and nothing else (gh#511) — row dividers are untouched (the perimeter is split onto its own --table-perimeter token, defaulting to --table-border). For card-composed tables: the card owns the frame, so the table's square perimeter otherwise renders a doubled edge (flush bleed) or a stray inner box (with content above). Standalone tables keep their chrome by default. Theming path without the attribute: set --table-perimeter to transparent per instance. Note: `<card-ui><section bleed>` already drops a direct-child table-ui's chrome automatically (card.css, gh#796) — `frameless`/`raw` on the instance still applies and is honored, but is no longer required just to avoid the doubled-edge look in that composition.",
|
|
44
44
|
"type": "boolean",
|
|
45
45
|
"default": false
|
|
46
46
|
},
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"default": 0
|
|
56
56
|
},
|
|
57
57
|
"raw": {
|
|
58
|
-
"description": "Visual-only passthrough — applies `<table-ui>`'s chrome reset (background / border / border-radius all transparent) AND short-circuits the data lifecycle entirely. The consumer owns the body shape: no header injection, no row reconciliation from `.data`, no empty-state / loading overlays, no aggregation or pagination footers. Use raw when embedding `<table-ui>` inside surfaces that supply their own chrome (e.g. `<card-ui><section bleed>`), or when wrapping a consumer-authored native `<table>` for design-token styling without the framework's data semantics. Pre-v0.6.33 (FB-53 §2) `raw` was visual-only and the data lifecycle still ran — wrapping a `.data`-unset native table produced a phantom \"No data\" overlay. v0.6.33+ matches the documented contract.",
|
|
58
|
+
"description": "Visual-only passthrough — applies `<table-ui>`'s chrome reset (background / border / border-radius all transparent) AND short-circuits the data lifecycle entirely. The consumer owns the body shape: no header injection, no row reconciliation from `.data`, no empty-state / loading overlays, no aggregation or pagination footers. Use raw when embedding `<table-ui>` inside surfaces that supply their own chrome (e.g. `<card-ui><section bleed>`), or when wrapping a consumer-authored native `<table>` for design-token styling without the framework's data semantics. Note: a `<table-ui>` placed directly inside `<card-ui><section bleed>` drops the table's visual chrome automatically (card.css, gh#796) even without `raw` — `raw` is still required to also short-circuit the data lifecycle. Pre-v0.6.33 (FB-53 §2) `raw` was visual-only and the data lifecycle still ran — wrapping a `.data`-unset native table produced a phantom \"No data\" overlay. v0.6.33+ matches the documented contract.",
|
|
59
59
|
"type": "boolean",
|
|
60
60
|
"default": false
|
|
61
61
|
},
|
|
@@ -94,13 +94,13 @@ export class UITable extends UIElement {
|
|
|
94
94
|
density: 'compact' | 'standard' | 'comfortable';
|
|
95
95
|
/** Enable row expansion */
|
|
96
96
|
expandable: boolean;
|
|
97
|
-
/** Drop the table's outer 1px perimeter and nothing else (gh#511) — row dividers are untouched (the perimeter is split onto its own --table-perimeter token, defaulting to --table-border). For card-composed tables: the card owns the frame, so the table's square perimeter otherwise renders a doubled edge (flush bleed) or a stray inner box (with content above). Standalone tables keep their chrome by default. Theming path without the attribute: set --table-perimeter to transparent per instance. */
|
|
97
|
+
/** Drop the table's outer 1px perimeter and nothing else (gh#511) — row dividers are untouched (the perimeter is split onto its own --table-perimeter token, defaulting to --table-border). For card-composed tables: the card owns the frame, so the table's square perimeter otherwise renders a doubled edge (flush bleed) or a stray inner box (with content above). Standalone tables keep their chrome by default. Theming path without the attribute: set --table-perimeter to transparent per instance. Note: `<card-ui><section bleed>` already drops a direct-child table-ui's chrome automatically (card.css, gh#796) — `frameless`/`raw` on the instance still applies and is honored, but is no longer required just to avoid the doubled-edge look in that composition. */
|
|
98
98
|
frameless: boolean;
|
|
99
99
|
/** Renders N ghost skeleton rows in place of the body data (count derived from `paginate` if set, else 5). Header + columns stay intact so the table layout is preserved while data fetches. Sets aria-busy="true" on the host. Data updates are deferred until loading is set back to false. */
|
|
100
100
|
loading: boolean;
|
|
101
101
|
/** Rows per page. 0 = show all rows without pagination. When > 0, renders a pagination bar below the table. */
|
|
102
102
|
paginate: number;
|
|
103
|
-
/** Visual-only passthrough — applies `<table-ui>`'s chrome reset (background / border / border-radius all transparent) AND short-circuits the data lifecycle entirely. The consumer owns the body shape: no header injection, no row reconciliation from `.data`, no empty-state / loading overlays, no aggregation or pagination footers. Use raw when embedding `<table-ui>` inside surfaces that supply their own chrome (e.g. `<card-ui><section bleed>`), or when wrapping a consumer-authored native `<table>` for design-token styling without the framework's data semantics. Pre-v0.6.33 (FB-53 §2) `raw` was visual-only and the data lifecycle still ran — wrapping a `.data`-unset native table produced a phantom "No data" overlay. v0.6.33+ matches the documented contract. */
|
|
103
|
+
/** Visual-only passthrough — applies `<table-ui>`'s chrome reset (background / border / border-radius all transparent) AND short-circuits the data lifecycle entirely. The consumer owns the body shape: no header injection, no row reconciliation from `.data`, no empty-state / loading overlays, no aggregation or pagination footers. Use raw when embedding `<table-ui>` inside surfaces that supply their own chrome (e.g. `<card-ui><section bleed>`), or when wrapping a consumer-authored native `<table>` for design-token styling without the framework's data semantics. Note: a `<table-ui>` placed directly inside `<card-ui><section bleed>` drops the table's visual chrome automatically (card.css, gh#796) even without `raw` — `raw` is still required to also short-circuit the data lifecycle. Pre-v0.6.33 (FB-53 §2) `raw` was visual-only and the data lifecycle still ran — wrapping a `.data`-unset native table produced a phantom "No data" overlay. v0.6.33+ matches the documented contract. */
|
|
104
104
|
raw: boolean;
|
|
105
105
|
/** Global search/filter string. Filters visible rows across all columns using case-insensitive substring matching. Resets to page 1 on change. */
|
|
106
106
|
search: string;
|
|
@@ -115,11 +115,6 @@ export class UITable extends UIElement {
|
|
|
115
115
|
/** Allow body-cell content to wrap onto multiple lines. Default is single-line with ellipsis truncation (matches the row convention shared by <select-ui> + <nav-item-ui>); long unbreakable strings clip gracefully rather than rewrapping the row. With [wrap], row height auto-grows to fit wrapped content. For surgical opt-in on a single column, set [data-wrap] on the cell / col-def instead. */
|
|
116
116
|
wrap: boolean;
|
|
117
117
|
|
|
118
|
-
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
119
|
-
type: K,
|
|
120
|
-
listener: (this: UITable, ev: HTMLElementEventMap[K]) => unknown,
|
|
121
|
-
options?: boolean | AddEventListenerOptions,
|
|
122
|
-
): void;
|
|
123
118
|
addEventListener(type: 'cell-click', listener: (ev: TableCellClickEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
124
119
|
addEventListener(type: 'filter-change', listener: (ev: TableFilterChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
125
120
|
addEventListener(type: 'page', listener: (ev: TablePageEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
@@ -129,4 +124,9 @@ export class UITable extends UIElement {
|
|
|
129
124
|
addEventListener(type: 'row-expand', listener: (ev: TableRowExpandEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
130
125
|
addEventListener(type: 'select', listener: (ev: TableSelectEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
131
126
|
addEventListener(type: 'sort', listener: (ev: TableSortEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
127
|
+
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
128
|
+
type: K,
|
|
129
|
+
listener: (this: UITable, ev: HTMLElementEventMap[K]) => unknown,
|
|
130
|
+
options?: boolean | AddEventListenerOptions,
|
|
131
|
+
): void;
|
|
132
132
|
}
|
|
@@ -74,6 +74,10 @@ props:
|
|
|
74
74
|
surfaces that supply their own chrome (e.g. `<card-ui><section
|
|
75
75
|
bleed>`), or when wrapping a consumer-authored native `<table>`
|
|
76
76
|
for design-token styling without the framework's data semantics.
|
|
77
|
+
Note: a `<table-ui>` placed directly inside `<card-ui><section bleed>`
|
|
78
|
+
drops the table's visual chrome automatically (card.css, gh#796) even
|
|
79
|
+
without `raw` — `raw` is still required to also short-circuit the
|
|
80
|
+
data lifecycle.
|
|
77
81
|
Pre-v0.6.33 (FB-53 §2) `raw` was visual-only and the data lifecycle
|
|
78
82
|
still ran — wrapping a `.data`-unset native table produced a
|
|
79
83
|
phantom "No data" overlay. v0.6.33+ matches the documented contract.
|
|
@@ -107,7 +111,11 @@ props:
|
|
|
107
111
|
square perimeter otherwise renders a doubled edge (flush bleed) or
|
|
108
112
|
a stray inner box (with content above). Standalone tables keep
|
|
109
113
|
their chrome by default. Theming path without the attribute:
|
|
110
|
-
set --table-perimeter to transparent per instance.
|
|
114
|
+
set --table-perimeter to transparent per instance. Note:
|
|
115
|
+
`<card-ui><section bleed>` already drops a direct-child table-ui's
|
|
116
|
+
chrome automatically (card.css, gh#796) — `frameless`/`raw` on the
|
|
117
|
+
instance still applies and is honored, but is no longer required
|
|
118
|
+
just to avoid the doubled-edge look in that composition.
|
|
111
119
|
type: boolean
|
|
112
120
|
default: false
|
|
113
121
|
reflect: true
|
|
@@ -37,13 +37,13 @@ export class UITableToolbar extends UIElement {
|
|
|
37
37
|
/** Toolbar visual variant. `default` renders bare on parent surface; `card` adds the same chrome as a card-ui header. */
|
|
38
38
|
variant: 'default' | 'card';
|
|
39
39
|
|
|
40
|
+
addEventListener(type: 'columns-change', listener: (ev: TableToolbarColumnsChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
41
|
+
addEventListener(type: 'filter-change', listener: (ev: TableToolbarFilterChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
42
|
+
addEventListener(type: 'search', listener: (ev: TableToolbarSearchEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
43
|
+
addEventListener(type: 'sort-change', listener: (ev: TableToolbarSortChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
40
44
|
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
41
45
|
type: K,
|
|
42
46
|
listener: (this: UITableToolbar, ev: HTMLElementEventMap[K]) => unknown,
|
|
43
47
|
options?: boolean | AddEventListenerOptions,
|
|
44
48
|
): void;
|
|
45
|
-
addEventListener(type: 'columns-change', listener: (ev: TableToolbarColumnsChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
46
|
-
addEventListener(type: 'filter-change', listener: (ev: TableToolbarFilterChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
47
|
-
addEventListener(type: 'search', listener: (ev: TableToolbarSearchEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
48
|
-
addEventListener(type: 'sort-change', listener: (ev: TableToolbarSortChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
49
49
|
}
|
package/components/tabs/tabs.css
CHANGED
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
--tabs-bg: transparent;
|
|
6
6
|
--tabs-radius: var(--a-radius-md);
|
|
7
7
|
--tabs-button-height: var(--a-size);
|
|
8
|
-
--tabs-button-px: var(--a-space-2);
|
|
9
8
|
--tabs-font-size: var(--a-ui-md);
|
|
10
9
|
--tabs-font-family: var(--a-font-family-ui);
|
|
11
|
-
|
|
10
|
+
/* Strip owns the button-to-button spacing — 4px base gap + one
|
|
11
|
+
padding unit (8px) folded in, since tab-button carries no
|
|
12
|
+
horizontal padding of its own (gh#705). */
|
|
13
|
+
--tabs-gap: var(--a-space-3);
|
|
12
14
|
--tabs-indicator-color: var(--md-sys-color-primary);
|
|
13
15
|
--tabs-indicator-height: 2px;
|
|
14
16
|
--tabs-fg: var(--md-sys-color-neutral-on-surface-variant);
|
|
@@ -101,6 +103,13 @@
|
|
|
101
103
|
height var(--tabs-duration) var(--tabs-easing-out);
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
/* Vertical: the indicator lives on the inline-start edge (not the bottom),
|
|
107
|
+
so contents need clearance from the line — the horizontal strip-gap
|
|
108
|
+
spacing (gh#705) can't provide it on this axis. */
|
|
109
|
+
:scope[orientation="vertical"] [slot="tab-button"] {
|
|
110
|
+
padding-inline-start: var(--a-space-3);
|
|
111
|
+
}
|
|
112
|
+
|
|
104
113
|
/* Vertical panel area takes remaining space */
|
|
105
114
|
:scope[orientation="vertical"] > tab-ui {
|
|
106
115
|
flex: 1;
|
|
@@ -114,7 +123,6 @@
|
|
|
114
123
|
align-items: center;
|
|
115
124
|
gap: var(--tabs-button-gap);
|
|
116
125
|
height: var(--tabs-button-height);
|
|
117
|
-
padding-inline: var(--tabs-button-px);
|
|
118
126
|
border: none;
|
|
119
127
|
background: none;
|
|
120
128
|
color: var(--tabs-fg);
|