@adia-ai/web-components 0.0.23 → 0.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/button/button.css +7 -5
- package/components/check/check.css +24 -27
- package/components/drawer/drawer.css +356 -349
- package/components/drawer/drawer.js +44 -11
- package/components/input/input.css +13 -11
- package/components/kbd/kbd.css +1 -1
- package/components/modal/modal.js +12 -11
- package/components/option-card/option-card.css +28 -36
- package/components/radio/radio.css +13 -14
- package/components/range/range.css +8 -4
- package/components/segment/segment.css +7 -7
- package/components/switch/switch.css +13 -11
- package/components/textarea/textarea.css +10 -5
- package/components/toast/toast.css +27 -26
- package/components/toggle-group/toggle-group.css +4 -3
- package/components/tree/tree.css +21 -9
- package/package.json +1 -1
- package/patterns/app-nav-item/app-nav-item.css +24 -24
- package/patterns/section-nav-item/section-nav-item.css +23 -24
|
@@ -36,7 +36,6 @@ class AdiaDrawer extends AdiaElement {
|
|
|
36
36
|
#closing = false;
|
|
37
37
|
#previousFocus = null;
|
|
38
38
|
#closeTimer = null;
|
|
39
|
-
#openRaf = null;
|
|
40
39
|
#dialogRef = null;
|
|
41
40
|
|
|
42
41
|
static properties = {
|
|
@@ -60,6 +59,28 @@ class AdiaDrawer extends AdiaElement {
|
|
|
60
59
|
// html`` result would trigger stamp() → replaceChildren(), wiping authored
|
|
61
60
|
// [slot=header|body|footer] before render() can migrate them into the panel.
|
|
62
61
|
|
|
62
|
+
constructor() {
|
|
63
|
+
super();
|
|
64
|
+
// Safari requires <dialog>.showModal() to be invoked synchronously inside
|
|
65
|
+
// the click handler. The reactive system schedules render() in a microtask
|
|
66
|
+
// after the property change, which Safari treats as outside the user-gesture
|
|
67
|
+
// window and silently no-ops the showModal. Wrap the auto-installed `open`
|
|
68
|
+
// setter so dialog state syncs in the same synchronous frame as the
|
|
69
|
+
// assignment. See docs/BROWSER-COMPAT.md §3a (Flavor C).
|
|
70
|
+
const desc = Object.getOwnPropertyDescriptor(this, 'open');
|
|
71
|
+
if (desc?.set) {
|
|
72
|
+
const origSet = desc.set;
|
|
73
|
+
Object.defineProperty(this, 'open', {
|
|
74
|
+
get: desc.get,
|
|
75
|
+
set: (v) => {
|
|
76
|
+
origSet.call(this, v);
|
|
77
|
+
this.#syncDialog();
|
|
78
|
+
},
|
|
79
|
+
configurable: true,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
63
84
|
#onPress = (e) => {
|
|
64
85
|
if (e.target.closest('[slot="close"]')) this.open = false;
|
|
65
86
|
};
|
|
@@ -101,10 +122,6 @@ class AdiaDrawer extends AdiaElement {
|
|
|
101
122
|
this.#dialogRef.removeEventListener('close', this.#onDialogClose);
|
|
102
123
|
this.#dialogRef.removeEventListener('click', this.#onDialogClick);
|
|
103
124
|
}
|
|
104
|
-
if (this.#openRaf != null) {
|
|
105
|
-
cancelAnimationFrame(this.#openRaf);
|
|
106
|
-
this.#openRaf = null;
|
|
107
|
-
}
|
|
108
125
|
if (this.#closeTimer != null) {
|
|
109
126
|
clearTimeout(this.#closeTimer);
|
|
110
127
|
this.#closeTimer = null;
|
|
@@ -228,15 +245,26 @@ class AdiaDrawer extends AdiaElement {
|
|
|
228
245
|
if (userFooter.parentElement !== panel) panel.appendChild(userFooter);
|
|
229
246
|
}
|
|
230
247
|
|
|
231
|
-
// Sync open state
|
|
248
|
+
// Sync open state — also syncs synchronously from the `open` setter
|
|
249
|
+
// (see constructor) so showModal() runs in the click handler's gesture
|
|
250
|
+
// frame on Safari.
|
|
251
|
+
this.#syncDialog();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
#syncDialog() {
|
|
255
|
+
const dialog = this.#dialogRef;
|
|
256
|
+
if (!dialog) return;
|
|
232
257
|
if (this.open && !dialog.open) {
|
|
233
258
|
this.#closing = false;
|
|
234
259
|
this.#previousFocus = document.activeElement;
|
|
235
260
|
dialog.showModal();
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
261
|
+
// Synchronous reflow instead of rAF — Safari throttles
|
|
262
|
+
// requestAnimationFrame when a top-layer dialog is open, sometimes
|
|
263
|
+
// delaying [data-open] (and the slide-in transition) by tens of
|
|
264
|
+
// seconds. Forcing a reflow keeps the animation start in the same
|
|
265
|
+
// synchronous frame. See docs/BROWSER-COMPAT.md §3a (Flavor C).
|
|
266
|
+
void dialog.offsetHeight;
|
|
267
|
+
dialog.setAttribute('data-open', '');
|
|
240
268
|
} else if (!this.open && dialog.open && !this.#closing) {
|
|
241
269
|
this.#animateClose(dialog);
|
|
242
270
|
}
|
|
@@ -244,8 +272,13 @@ class AdiaDrawer extends AdiaElement {
|
|
|
244
272
|
|
|
245
273
|
#animateClose(dialog) {
|
|
246
274
|
this.#closing = true;
|
|
247
|
-
|
|
275
|
+
// Set [data-closing] FIRST (carries the transition spec), force a
|
|
276
|
+
// reflow, THEN remove [data-open]. If both attribute changes batch
|
|
277
|
+
// into a single style update, Safari can skip the slide-out animation
|
|
278
|
+
// entirely.
|
|
248
279
|
dialog.setAttribute('data-closing', '');
|
|
280
|
+
void dialog.offsetHeight;
|
|
281
|
+
dialog.removeAttribute('data-open');
|
|
249
282
|
|
|
250
283
|
this.#closeTimer = setTimeout(() => {
|
|
251
284
|
this.#closeTimer = null;
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
/* Safari 17.x bug: `:scope[attr]:hover`
|
|
2
|
-
scope root. Plain
|
|
1
|
+
/* Safari 17.x bug: `:scope[attr]:hover` and `:scope:not(...) [descendant]:hover`
|
|
2
|
+
inside `@scope` don't match the scope root. Plain selectors outside work.
|
|
3
|
+
See docs/BROWSER-COMPAT.md §3a. */
|
|
3
4
|
input-ui[variant="ghost"]:hover {
|
|
4
5
|
--input-bg: var(--a-bg-muted);
|
|
5
6
|
}
|
|
7
|
+
input-ui:not([disabled]) [slot="field"]:hover {
|
|
8
|
+
background: var(--input-bg-hover);
|
|
9
|
+
border-color: var(--input-border-hover);
|
|
10
|
+
color: var(--input-fg-hover);
|
|
11
|
+
}
|
|
12
|
+
input-ui:not([disabled]) [slot="field"]:hover [slot="prefix"],
|
|
13
|
+
input-ui:not([disabled]) [slot="field"]:hover [slot="suffix"] {
|
|
14
|
+
color: var(--input-affix-fg-hover);
|
|
15
|
+
}
|
|
6
16
|
|
|
7
17
|
@scope (input-ui) {
|
|
8
18
|
:where(:scope) {
|
|
@@ -83,15 +93,7 @@ input-ui[variant="ghost"]:hover {
|
|
|
83
93
|
color var(--input-duration) var(--input-easing),
|
|
84
94
|
box-shadow var(--input-duration) var(--input-easing);
|
|
85
95
|
}
|
|
86
|
-
|
|
87
|
-
background: var(--input-bg-hover);
|
|
88
|
-
border-color: var(--input-border-hover);
|
|
89
|
-
color: var(--input-fg-hover);
|
|
90
|
-
}
|
|
91
|
-
:scope:not([disabled]) [slot="field"]:hover [slot="prefix"],
|
|
92
|
-
:scope:not([disabled]) [slot="field"]:hover [slot="suffix"] {
|
|
93
|
-
color: var(--input-affix-fg-hover);
|
|
94
|
-
}
|
|
96
|
+
/* hover rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
95
97
|
:scope:not([disabled]):focus-within [slot="field"] {
|
|
96
98
|
/* Canonical ring — consumes the L3 --input-focus-ring token
|
|
97
99
|
which aliases --a-focus-ring. Border stays stable; the ring
|
package/components/kbd/kbd.css
CHANGED
|
@@ -36,7 +36,6 @@ class AdiaModal extends AdiaElement {
|
|
|
36
36
|
#closing = false;
|
|
37
37
|
#previousFocus = null;
|
|
38
38
|
#closeTimer = null;
|
|
39
|
-
#openRaf = null;
|
|
40
39
|
#dialogRef = null;
|
|
41
40
|
|
|
42
41
|
static properties = {
|
|
@@ -101,10 +100,6 @@ class AdiaModal extends AdiaElement {
|
|
|
101
100
|
this.#dialogRef.removeEventListener('close', this.#onDialogClose);
|
|
102
101
|
this.#dialogRef.removeEventListener('click', this.#onDialogClick);
|
|
103
102
|
}
|
|
104
|
-
if (this.#openRaf != null) {
|
|
105
|
-
cancelAnimationFrame(this.#openRaf);
|
|
106
|
-
this.#openRaf = null;
|
|
107
|
-
}
|
|
108
103
|
if (this.#closeTimer != null) {
|
|
109
104
|
clearTimeout(this.#closeTimer);
|
|
110
105
|
this.#closeTimer = null;
|
|
@@ -185,15 +180,16 @@ class AdiaModal extends AdiaElement {
|
|
|
185
180
|
if (footer.parentElement !== panel) panel.appendChild(footer);
|
|
186
181
|
}
|
|
187
182
|
|
|
188
|
-
// Sync open state
|
|
183
|
+
// Sync open state. Synchronous reflow instead of rAF — Safari throttles
|
|
184
|
+
// requestAnimationFrame when a top-layer dialog is open, sometimes
|
|
185
|
+
// delaying [data-open] (and the scale-in transition) by tens of seconds.
|
|
186
|
+
// See docs/BROWSER-COMPAT.md §3a (Flavor C).
|
|
189
187
|
if (this.open && !dialog.open) {
|
|
190
188
|
this.#closing = false;
|
|
191
189
|
this.#previousFocus = document.activeElement;
|
|
192
190
|
dialog.showModal();
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
dialog.setAttribute('data-open', '');
|
|
196
|
-
});
|
|
191
|
+
void dialog.offsetHeight;
|
|
192
|
+
dialog.setAttribute('data-open', '');
|
|
197
193
|
} else if (!this.open && dialog.open && !this.#closing) {
|
|
198
194
|
this.#animateClose(dialog);
|
|
199
195
|
}
|
|
@@ -201,8 +197,13 @@ class AdiaModal extends AdiaElement {
|
|
|
201
197
|
|
|
202
198
|
#animateClose(dialog) {
|
|
203
199
|
this.#closing = true;
|
|
204
|
-
|
|
200
|
+
// Set [data-closing] FIRST (carries the transition spec), force a
|
|
201
|
+
// reflow, THEN remove [data-open]. If both attribute changes batch
|
|
202
|
+
// into a single style update, Safari can skip the fade-out animation
|
|
203
|
+
// entirely.
|
|
205
204
|
dialog.setAttribute('data-closing', '');
|
|
205
|
+
void dialog.offsetHeight;
|
|
206
|
+
dialog.removeAttribute('data-open');
|
|
206
207
|
|
|
207
208
|
this.#closeTimer = setTimeout(() => {
|
|
208
209
|
this.#closeTimer = null;
|
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
/* Safari 17.x bug: `:scope:not(...):hover`
|
|
2
|
-
|
|
3
|
-
docs/BROWSER-COMPAT.md §3a. */
|
|
1
|
+
/* Safari 17.x bug: `:scope:not(...):hover` (Flavor A) and `:scope[checked]`
|
|
2
|
+
(Flavor B — attribute-removal restyle) both fail inside `@scope`.
|
|
3
|
+
Selectors moved out. See docs/BROWSER-COMPAT.md §3a. */
|
|
4
4
|
option-card-ui:not([checked]):not([disabled]):hover {
|
|
5
5
|
background: var(--option-card-bg-hover);
|
|
6
6
|
border-color: var(--option-card-border-hover);
|
|
7
7
|
}
|
|
8
|
+
option-card-ui[checked] > :not([slot]) {
|
|
9
|
+
display: block;
|
|
10
|
+
}
|
|
11
|
+
option-card-ui[checked] {
|
|
12
|
+
background: var(--option-card-bg-checked);
|
|
13
|
+
border-color: var(--option-card-border-checked);
|
|
14
|
+
}
|
|
15
|
+
option-card-ui[checked]::before {
|
|
16
|
+
border-color: var(--option-card-radio-fill);
|
|
17
|
+
background:
|
|
18
|
+
radial-gradient(
|
|
19
|
+
circle,
|
|
20
|
+
var(--option-card-radio-dot) 0 30%,
|
|
21
|
+
var(--option-card-radio-fill) 30% 100%
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
option-card-ui[checked] > [slot="heading"] {
|
|
25
|
+
color: var(--option-card-heading-color-checked);
|
|
26
|
+
}
|
|
27
|
+
option-card-ui[checked] > [slot="icon"] {
|
|
28
|
+
color: var(--option-card-icon-color-checked);
|
|
29
|
+
}
|
|
8
30
|
|
|
9
31
|
@scope (option-card-ui) {
|
|
10
32
|
:where(:scope) {
|
|
@@ -142,39 +164,9 @@ option-card-ui:not([checked]):not([disabled]):hover {
|
|
|
142
164
|
:scope:has(> [slot="icon"]) > :not([slot]) {
|
|
143
165
|
grid-column: 3 / -1;
|
|
144
166
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
/* hover rule moved outside @scope — see Safari 17.x bug note at top. */
|
|
150
|
-
|
|
151
|
-
/* ── State: checked — accent border + tinted bg + filled radio.
|
|
152
|
-
The indicator becomes an accent disc with a centered dot of
|
|
153
|
-
--option-card-radio-dot at 60% of the size, mirroring
|
|
154
|
-
radio-ui's recipe (radio.css:75-78). Done with a radial
|
|
155
|
-
gradient so a single pseudo-element carries both layers. */
|
|
156
|
-
:scope[checked] {
|
|
157
|
-
background: var(--option-card-bg-checked);
|
|
158
|
-
border-color: var(--option-card-border-checked);
|
|
159
|
-
}
|
|
160
|
-
:scope[checked]::before {
|
|
161
|
-
border-color: var(--option-card-radio-fill);
|
|
162
|
-
background:
|
|
163
|
-
radial-gradient(
|
|
164
|
-
circle,
|
|
165
|
-
var(--option-card-radio-dot) 0 30%,
|
|
166
|
-
var(--option-card-radio-fill) 30% 100%
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
/* Heading + icon shift to a strong color when checked — gives the
|
|
170
|
-
selected card a clear text-level emphasis on top of the bg/border
|
|
171
|
-
state, so picking is unambiguous beyond the radio dot alone. */
|
|
172
|
-
:scope[checked] > [slot="heading"] {
|
|
173
|
-
color: var(--option-card-heading-color-checked);
|
|
174
|
-
}
|
|
175
|
-
:scope[checked] > [slot="icon"] {
|
|
176
|
-
color: var(--option-card-icon-color-checked);
|
|
177
|
-
}
|
|
167
|
+
/* hover + [checked] state rules moved outside @scope — see Safari 17.x bug note at top.
|
|
168
|
+
The :scope[checked]::before recipe lives at top-of-file: an accent disc
|
|
169
|
+
with a centered dot via radial-gradient, mirroring radio-ui's recipe. */
|
|
178
170
|
|
|
179
171
|
/* ── Layout: tile — icon top-left, indicator top-right, heading +
|
|
180
172
|
description below, all left-aligned. Used for hero pickers
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
/* Safari 17.x bug: `:scope*:hover [descendant]`
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/* Safari 17.x bug: `:scope*:hover [descendant]` (Flavor A) and
|
|
2
|
+
`:scope[checked] [descendant]` (Flavor B — attribute-removal restyle)
|
|
3
|
+
both fail inside `@scope`. Selectors moved out. See
|
|
4
|
+
docs/BROWSER-COMPAT.md §3a. */
|
|
4
5
|
radio-ui:not([disabled]):hover [slot="dot"] {
|
|
5
6
|
border-color: var(--radio-border-hover);
|
|
6
7
|
background: var(--radio-bg-hover);
|
|
@@ -9,6 +10,14 @@ radio-ui[checked]:not([disabled]):hover [slot="dot"] {
|
|
|
9
10
|
background: var(--radio-bg-checked-hover);
|
|
10
11
|
border-color: var(--radio-bg-checked-hover);
|
|
11
12
|
}
|
|
13
|
+
radio-ui[checked] [slot="dot"] {
|
|
14
|
+
background: var(--radio-bg-checked);
|
|
15
|
+
border-color: var(--radio-border-checked);
|
|
16
|
+
}
|
|
17
|
+
radio-ui[checked] [slot="dot"]::after {
|
|
18
|
+
width: calc(var(--radio-size) * 0.6);
|
|
19
|
+
height: calc(var(--radio-size) * 0.6);
|
|
20
|
+
}
|
|
12
21
|
|
|
13
22
|
@scope (radio-ui) {
|
|
14
23
|
:where(:scope) {
|
|
@@ -84,17 +93,7 @@ radio-ui[checked]:not([disabled]):hover [slot="dot"] {
|
|
|
84
93
|
height var(--radio-duration) var(--radio-easing);
|
|
85
94
|
}
|
|
86
95
|
|
|
87
|
-
|
|
88
|
-
width: calc(var(--radio-size) * 0.6);
|
|
89
|
-
height: calc(var(--radio-size) * 0.6);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/* hover rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
93
|
-
|
|
94
|
-
:scope[checked] [slot="dot"] {
|
|
95
|
-
background: var(--radio-bg-checked);
|
|
96
|
-
border-color: var(--radio-border-checked);
|
|
97
|
-
}
|
|
96
|
+
/* hover + [checked] rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
98
97
|
|
|
99
98
|
/* Label */
|
|
100
99
|
:scope[label]::after { content: attr(label); }
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/* Safari 17.x bug: `:scope:not(...) [descendant]:hover` inside `@scope`
|
|
2
|
+
doesn't match the scope root. Plain selector outside works. See
|
|
3
|
+
docs/BROWSER-COMPAT.md §3a. */
|
|
4
|
+
range-ui:not([disabled]) [slot="field"]:hover [data-layer="fill"] {
|
|
5
|
+
background: var(--range-fill-bg-hover);
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
@scope (range-ui) {
|
|
2
9
|
:where(:scope) {
|
|
3
10
|
/* ── Tokens (wired to --a-ui-*) ── */
|
|
@@ -127,10 +134,7 @@
|
|
|
127
134
|
color: var(--range-label-fg-hover);
|
|
128
135
|
}
|
|
129
136
|
|
|
130
|
-
/* Hover
|
|
131
|
-
:scope:not([disabled]) [slot="field"]:hover [data-layer="fill"] {
|
|
132
|
-
background: var(--range-fill-bg-hover);
|
|
133
|
-
}
|
|
137
|
+
/* Hover-fill brighten moved outside @scope — see Safari 17.x bug note at top. */
|
|
134
138
|
|
|
135
139
|
/* Dragging: deepest fill, sharper border, instant (no transition lag on the clip) */
|
|
136
140
|
:scope[data-dragging] [slot="field"] {
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
/* Safari 17.x bug: `:scope:not(...):hover`
|
|
2
|
-
|
|
3
|
-
docs/BROWSER-COMPAT.md §3a. */
|
|
1
|
+
/* Safari 17.x bug: `:scope:not(...):hover` (Flavor A) and `:scope[selected]`
|
|
2
|
+
(Flavor B — attribute-removal restyle) both fail inside `@scope`.
|
|
3
|
+
Selectors moved out. See docs/BROWSER-COMPAT.md §3a. */
|
|
4
4
|
segment-ui:not([disabled]):not([selected]):hover {
|
|
5
5
|
color: var(--segment-fg-hover);
|
|
6
6
|
}
|
|
7
|
+
segment-ui[selected] {
|
|
8
|
+
color: var(--segment-fg-selected);
|
|
9
|
+
}
|
|
7
10
|
|
|
8
11
|
@scope (segment-ui) {
|
|
9
12
|
:where(:scope) {
|
|
@@ -80,10 +83,7 @@ segment-ui:not([disabled]):not([selected]):hover {
|
|
|
80
83
|
white-space: nowrap;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
/* States — hover
|
|
84
|
-
:scope[selected] {
|
|
85
|
-
color: var(--segment-fg-selected);
|
|
86
|
-
}
|
|
86
|
+
/* States — hover + [selected] rules moved outside @scope; see Safari 17.x bug note at top. */
|
|
87
87
|
|
|
88
88
|
:scope:focus-visible {
|
|
89
89
|
outline: none;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
/* Safari 17.x bug: `:scope[attr]:hover`
|
|
2
|
-
|
|
1
|
+
/* Safari 17.x bug: `:scope[attr]:hover` (Flavor A) and `:scope[checked]`
|
|
2
|
+
token-block (Flavor B — attribute-removal restyle) both fail inside
|
|
3
|
+
`@scope`. Selectors moved out. See docs/BROWSER-COMPAT.md §3a. */
|
|
3
4
|
switch-ui:not([disabled]):hover {
|
|
4
5
|
--switch-track-bg: var(--switch-track-bg-hover);
|
|
5
6
|
--switch-track-border: var(--switch-track-border-hover);
|
|
@@ -8,6 +9,14 @@ switch-ui[checked]:not([disabled]):hover {
|
|
|
8
9
|
--switch-track-bg: var(--switch-track-bg-checked-hover);
|
|
9
10
|
--switch-track-border: var(--switch-track-border-checked-hover);
|
|
10
11
|
}
|
|
12
|
+
switch-ui[checked] {
|
|
13
|
+
--switch-track-bg: var(--switch-track-bg-checked);
|
|
14
|
+
--switch-track-border: var(--switch-track-border-checked);
|
|
15
|
+
--switch-thumb-bg: var(--switch-thumb-bg-checked);
|
|
16
|
+
}
|
|
17
|
+
switch-ui[checked] [slot="thumb"] {
|
|
18
|
+
transform: translateX(var(--switch-thumb-travel));
|
|
19
|
+
}
|
|
11
20
|
|
|
12
21
|
@scope (switch-ui) {
|
|
13
22
|
:where(:scope) {
|
|
@@ -77,12 +86,7 @@ switch-ui[checked]:not([disabled]):hover {
|
|
|
77
86
|
background var(--switch-duration) var(--switch-easing),
|
|
78
87
|
border-color var(--switch-duration) var(--switch-easing);
|
|
79
88
|
}
|
|
80
|
-
/* hover rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
81
|
-
:scope[checked] {
|
|
82
|
-
--switch-track-bg: var(--switch-track-bg-checked);
|
|
83
|
-
--switch-track-border: var(--switch-track-border-checked);
|
|
84
|
-
--switch-thumb-bg: var(--switch-thumb-bg-checked);
|
|
85
|
-
}
|
|
89
|
+
/* hover + [checked] rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
86
90
|
|
|
87
91
|
[slot="thumb"] {
|
|
88
92
|
position: absolute;
|
|
@@ -97,9 +101,7 @@ switch-ui[checked]:not([disabled]):hover {
|
|
|
97
101
|
transform var(--switch-duration) var(--switch-easing),
|
|
98
102
|
background var(--switch-duration) var(--switch-easing);
|
|
99
103
|
}
|
|
100
|
-
:scope[checked] [slot="thumb"]
|
|
101
|
-
transform: translateX(var(--switch-thumb-travel));
|
|
102
|
-
}
|
|
104
|
+
/* :scope[checked] [slot="thumb"] moved outside @scope — see Safari 17.x bug note at top. */
|
|
103
105
|
|
|
104
106
|
[slot="label"] { font-size: var(--switch-font-size); }
|
|
105
107
|
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/* Safari 17.x bug: `:scope:not(...) [descendant]:hover` inside `@scope`
|
|
2
|
+
doesn't match the scope root. Plain selector outside works. See
|
|
3
|
+
docs/BROWSER-COMPAT.md §3a. */
|
|
4
|
+
textarea-ui:not([disabled]) [slot="text"]:hover {
|
|
5
|
+
background: var(--textarea-bg-hover);
|
|
6
|
+
border-color: var(--textarea-border-hover);
|
|
7
|
+
color: var(--textarea-fg-hover);
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
@scope (textarea-ui) {
|
|
2
11
|
:where(:scope) {
|
|
3
12
|
/* ── Tokens (wired to --a-ui-*) ── */
|
|
@@ -66,11 +75,7 @@
|
|
|
66
75
|
outline: none;
|
|
67
76
|
transition: border-color var(--textarea-duration) var(--textarea-easing);
|
|
68
77
|
}
|
|
69
|
-
|
|
70
|
-
background: var(--textarea-bg-hover);
|
|
71
|
-
border-color: var(--textarea-border-hover);
|
|
72
|
-
color: var(--textarea-fg-hover);
|
|
73
|
-
}
|
|
78
|
+
/* hover rule moved outside @scope — see Safari 17.x bug note at top. */
|
|
74
79
|
:scope:not([disabled]) [slot="text"]:focus {
|
|
75
80
|
/* Canonical ring via L3 token (see semantics.css FOCUS block).
|
|
76
81
|
`:focus` (not :focus-visible) is deliberate — the caret lives
|
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
TOAST-N — Notification popup with auto-dismiss.
|
|
3
3
|
═══════════════════════════════════════════════════════════════ */
|
|
4
4
|
|
|
5
|
+
/* Safari 17.x bug: `:scope[data-open]` and `:scope[data-closing]`
|
|
6
|
+
(Flavor B — attribute-removal restyle) don't reliably restyle on
|
|
7
|
+
attribute toggling inside `@scope`. Selectors moved out as plain
|
|
8
|
+
`toast-ui[data-…]` rules. See docs/BROWSER-COMPAT.md §3a. */
|
|
9
|
+
toast-ui[data-open] {
|
|
10
|
+
transition: transform var(--toast-duration) var(--toast-easing),
|
|
11
|
+
opacity var(--toast-duration) var(--toast-easing);
|
|
12
|
+
transform: translateY(0);
|
|
13
|
+
opacity: 1;
|
|
14
|
+
}
|
|
15
|
+
toast-ui[data-closing] {
|
|
16
|
+
transition: transform var(--toast-duration) var(--toast-easing),
|
|
17
|
+
opacity var(--toast-duration) var(--toast-easing);
|
|
18
|
+
opacity: 0;
|
|
19
|
+
}
|
|
20
|
+
toast-ui[data-closing],
|
|
21
|
+
toast-ui[data-closing][position="bottom-right"],
|
|
22
|
+
toast-ui[data-closing][position="bottom-left"] {
|
|
23
|
+
transform: translateY(1rem);
|
|
24
|
+
}
|
|
25
|
+
toast-ui[data-closing][position="top-right"],
|
|
26
|
+
toast-ui[data-closing][position="top-left"] {
|
|
27
|
+
transform: translateY(-1rem);
|
|
28
|
+
}
|
|
29
|
+
|
|
5
30
|
@scope (toast-ui) {
|
|
6
31
|
:where(:scope) {
|
|
7
32
|
--toast-bg: var(--a-bg-subtle);
|
|
@@ -78,32 +103,8 @@
|
|
|
78
103
|
transform: translateY(-1rem);
|
|
79
104
|
}
|
|
80
105
|
|
|
81
|
-
/*
|
|
82
|
-
|
|
83
|
-
:scope[data-open] {
|
|
84
|
-
transition: transform var(--toast-duration) var(--toast-easing),
|
|
85
|
-
opacity var(--toast-duration) var(--toast-easing);
|
|
86
|
-
transform: translateY(0);
|
|
87
|
-
opacity: 1;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/* ── Exit animation ── */
|
|
91
|
-
|
|
92
|
-
:scope[data-closing] {
|
|
93
|
-
transition: transform var(--toast-duration) var(--toast-easing),
|
|
94
|
-
opacity var(--toast-duration) var(--toast-easing);
|
|
95
|
-
opacity: 0;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
:where(:scope[data-closing]),
|
|
99
|
-
:where(:scope[data-closing][position="bottom-right"]),
|
|
100
|
-
:where(:scope[data-closing][position="bottom-left"]) {
|
|
101
|
-
transform: translateY(1rem);
|
|
102
|
-
}
|
|
103
|
-
:where(:scope[data-closing][position="top-right"]),
|
|
104
|
-
:where(:scope[data-closing][position="top-left"]) {
|
|
105
|
-
transform: translateY(-1rem);
|
|
106
|
-
}
|
|
106
|
+
/* Enter / exit animation rules ([data-open] / [data-closing]) moved
|
|
107
|
+
outside @scope — see Safari 17.x bug note at top of file. */
|
|
107
108
|
|
|
108
109
|
/* ── Variant: info (default) ── */
|
|
109
110
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* Safari 17.x bug: `:scope:not(...):hover` inside `@scope` doesn't match
|
|
2
|
-
the scope root. Plain selector outside works.
|
|
3
|
-
|
|
4
|
-
toggle-
|
|
2
|
+
the scope root. Plain selector outside works. The @scope is
|
|
3
|
+
`(toggle-option-ui)` — NOT `(toggle-group-ui)` — so the moved-out
|
|
4
|
+
selector targets `toggle-option-ui:hover`. See docs/BROWSER-COMPAT.md §3a. */
|
|
5
|
+
toggle-option-ui:not([disabled]):hover {
|
|
5
6
|
--toggle-option-bg: var(--toggle-option-bg-hover);
|
|
6
7
|
--toggle-option-fg: var(--toggle-option-fg-hover);
|
|
7
8
|
}
|
package/components/tree/tree.css
CHANGED
|
@@ -90,10 +90,7 @@
|
|
|
90
90
|
box-shadow: var(--tree-focus-ring);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
:scope[selected]
|
|
94
|
-
background: var(--tree-bg-selected);
|
|
95
|
-
color: var(--tree-fg);
|
|
96
|
-
}
|
|
93
|
+
/* :scope[selected] rules moved outside @scope — see tree-ui Safari note at end of file. */
|
|
97
94
|
|
|
98
95
|
/* ── Chevron ── */
|
|
99
96
|
[slot="chevron"] {
|
|
@@ -120,9 +117,7 @@
|
|
|
120
117
|
flex-shrink: 0;
|
|
121
118
|
}
|
|
122
119
|
|
|
123
|
-
:scope[selected]
|
|
124
|
-
color: var(--tree-fg);
|
|
125
|
-
}
|
|
120
|
+
/* :scope[selected] icon override moved outside @scope — see Safari note at end of file. */
|
|
126
121
|
|
|
127
122
|
/* ── Text ── */
|
|
128
123
|
[slot="text"] {
|
|
@@ -142,13 +137,30 @@
|
|
|
142
137
|
transition: opacity var(--tree-duration) var(--tree-easing);
|
|
143
138
|
}
|
|
144
139
|
|
|
145
|
-
[slot="row"]:hover [slot="actions"]
|
|
146
|
-
:scope[selected] > [slot="row"] [slot="actions"] {
|
|
140
|
+
[slot="row"]:hover [slot="actions"] {
|
|
147
141
|
opacity: 1;
|
|
148
142
|
}
|
|
143
|
+
/* :scope[selected] > [slot="row"] [slot="actions"] moved outside @scope. */
|
|
149
144
|
|
|
150
145
|
/* ── Children — collapsed state ── */
|
|
151
146
|
:scope:not([open]) > tree-item-ui {
|
|
152
147
|
display: none;
|
|
153
148
|
}
|
|
154
149
|
}
|
|
150
|
+
|
|
151
|
+
/* Safari 17.x bug: `:scope[selected]` (Flavor B — attribute-removal restyle)
|
|
152
|
+
doesn't restyle on attribute removal inside `@scope`. Selectors moved
|
|
153
|
+
out as plain `tree-ui[selected] …` rules (the @scope is `(tree-ui)`, so
|
|
154
|
+
`:scope` resolved to `tree-ui`). Custom-property tokens from
|
|
155
|
+
`:where(:scope)` still resolve via inheritance. See
|
|
156
|
+
docs/BROWSER-COMPAT.md §3a. */
|
|
157
|
+
tree-ui[selected] > [slot="row"] {
|
|
158
|
+
background: var(--tree-bg-selected);
|
|
159
|
+
color: var(--tree-fg);
|
|
160
|
+
}
|
|
161
|
+
tree-ui[selected] > [slot="row"] [slot="icon"] {
|
|
162
|
+
color: var(--tree-fg);
|
|
163
|
+
}
|
|
164
|
+
tree-ui[selected] > [slot="row"] [slot="actions"] {
|
|
165
|
+
opacity: 1;
|
|
166
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/web-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"description": "AdiaUI web components — vanilla custom elements. A2UI runtime (renderer, registry, streams, wiring) lives in @adia-ai/a2ui-utils.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/* Safari 17.x bug: `:scope:hover`
|
|
2
|
-
|
|
3
|
-
`:where(:scope)`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
/* Safari 17.x bug: `:scope:hover` (Flavor A) and `:scope[selected]`
|
|
2
|
+
(Flavor B — attribute-removal restyle) both fail inside `@scope`.
|
|
3
|
+
Selectors moved out — custom props from `:where(:scope)` are still set
|
|
4
|
+
on the element via inheritance. Specificity (0,1,1 / 0,2,1) preserved.
|
|
5
|
+
Safari < 18 is below the §1 floor (ADR-0007); fix protects opt-in
|
|
6
|
+
consumers extending below the floor and is harmlessly redundant on
|
|
7
|
+
engines without the bug. */
|
|
8
8
|
app-nav-item-ui:hover {
|
|
9
9
|
background: var(--nav-item-bg-hover);
|
|
10
10
|
color: var(--nav-item-fg-hover);
|
|
@@ -12,6 +12,21 @@ app-nav-item-ui:hover {
|
|
|
12
12
|
app-nav-item-ui:hover [slot="icon"] {
|
|
13
13
|
color: var(--nav-item-fg-hover);
|
|
14
14
|
}
|
|
15
|
+
app-nav-item-ui[selected] {
|
|
16
|
+
background: var(--nav-item-bg-selected);
|
|
17
|
+
color: var(--nav-item-fg-selected);
|
|
18
|
+
font-weight: var(--nav-item-selected-weight);
|
|
19
|
+
}
|
|
20
|
+
app-nav-item-ui[selected] [slot="icon"] {
|
|
21
|
+
color: var(--nav-item-icon-fg-selected);
|
|
22
|
+
}
|
|
23
|
+
app-nav-item-ui[selected] [slot="icon"]:empty::before {
|
|
24
|
+
content: '';
|
|
25
|
+
width: 2px;
|
|
26
|
+
height: 1em;
|
|
27
|
+
border-radius: 1px;
|
|
28
|
+
background: var(--nav-item-accent);
|
|
29
|
+
}
|
|
15
30
|
|
|
16
31
|
@scope (app-nav-item-ui) {
|
|
17
32
|
:where(:scope) {
|
|
@@ -61,15 +76,7 @@ app-nav-item-ui:hover [slot="icon"] {
|
|
|
61
76
|
outline: none;
|
|
62
77
|
}
|
|
63
78
|
|
|
64
|
-
:scope[selected]
|
|
65
|
-
background: var(--nav-item-bg-selected);
|
|
66
|
-
color: var(--nav-item-fg-selected);
|
|
67
|
-
font-weight: var(--nav-item-selected-weight);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
:scope[selected] [slot="icon"] {
|
|
71
|
-
color: var(--nav-item-icon-fg-selected);
|
|
72
|
-
}
|
|
79
|
+
/* :scope[selected] rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
73
80
|
|
|
74
81
|
/* Icon slot — always present, reserves space even when empty */
|
|
75
82
|
[slot="icon"] {
|
|
@@ -87,14 +94,7 @@ app-nav-item-ui:hover [slot="icon"] {
|
|
|
87
94
|
--a-icon-size: calc(var(--nav-item-icon-font-size) + 2px);
|
|
88
95
|
}
|
|
89
96
|
|
|
90
|
-
/* Selected accent line
|
|
91
|
-
:scope[selected] [slot="icon"]:empty::before {
|
|
92
|
-
content: '';
|
|
93
|
-
width: 2px;
|
|
94
|
-
height: 1em;
|
|
95
|
-
border-radius: 1px;
|
|
96
|
-
background: var(--nav-item-accent);
|
|
97
|
-
}
|
|
97
|
+
/* Selected accent line on empty icon slot moved outside @scope — see Safari 17.x bug note at top. */
|
|
98
98
|
|
|
99
99
|
[slot="text"] {
|
|
100
100
|
flex: 1;
|