@adia-ai/web-components 0.0.22 → 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/action-list/action-list.css +13 -4
- package/components/avatar/avatar.css +8 -9
- package/components/button/button.css +30 -25
- package/components/check/check.css +34 -32
- package/components/drawer/drawer.css +356 -349
- package/components/drawer/drawer.js +44 -11
- package/components/input/input.css +19 -12
- package/components/kbd/kbd.css +1 -1
- package/components/menu/menu.css +22 -11
- package/components/modal/modal.js +12 -11
- package/components/option-card/option-card.css +33 -37
- package/components/radio/radio.css +22 -19
- package/components/range/range.css +8 -4
- package/components/rating/rating.css +7 -4
- package/components/segment/segment.css +11 -8
- package/components/switch/switch.css +22 -16
- package/components/tag/tag.css +7 -4
- package/components/textarea/textarea.css +10 -5
- package/components/toast/toast.css +27 -26
- package/components/toggle-group/toggle-group.css +10 -4
- package/components/tree/tree.css +21 -9
- package/package.json +1 -1
- package/patterns/app-nav/app-nav.js +13 -0
- package/patterns/app-nav-item/app-nav-item.css +32 -26
- package/patterns/section-nav-item/section-nav-item.css +31 -21
|
@@ -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,3 +1,19 @@
|
|
|
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. */
|
|
4
|
+
input-ui[variant="ghost"]:hover {
|
|
5
|
+
--input-bg: var(--a-bg-muted);
|
|
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
|
+
}
|
|
16
|
+
|
|
1
17
|
@scope (input-ui) {
|
|
2
18
|
:where(:scope) {
|
|
3
19
|
/* ── Tokens (wired to --a-ui-*) ── */
|
|
@@ -77,15 +93,7 @@
|
|
|
77
93
|
color var(--input-duration) var(--input-easing),
|
|
78
94
|
box-shadow var(--input-duration) var(--input-easing);
|
|
79
95
|
}
|
|
80
|
-
|
|
81
|
-
background: var(--input-bg-hover);
|
|
82
|
-
border-color: var(--input-border-hover);
|
|
83
|
-
color: var(--input-fg-hover);
|
|
84
|
-
}
|
|
85
|
-
:scope:not([disabled]) [slot="field"]:hover [slot="prefix"],
|
|
86
|
-
:scope:not([disabled]) [slot="field"]:hover [slot="suffix"] {
|
|
87
|
-
color: var(--input-affix-fg-hover);
|
|
88
|
-
}
|
|
96
|
+
/* hover rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
89
97
|
:scope:not([disabled]):focus-within [slot="field"] {
|
|
90
98
|
/* Canonical ring — consumes the L3 --input-focus-ring token
|
|
91
99
|
which aliases --a-focus-ring. Border stays stable; the ring
|
|
@@ -176,7 +184,6 @@
|
|
|
176
184
|
--input-border: transparent;
|
|
177
185
|
--input-border-hover: transparent;
|
|
178
186
|
}
|
|
179
|
-
:scope[variant="ghost"]:hover
|
|
180
|
-
|
|
181
|
-
}
|
|
187
|
+
/* :scope[variant="ghost"]:hover moved outside @scope — see Safari
|
|
188
|
+
17.x bug note at top of file. */
|
|
182
189
|
}
|
package/components/kbd/kbd.css
CHANGED
package/components/menu/menu.css
CHANGED
|
@@ -40,6 +40,28 @@ menu-ui [data-menu-popover] {
|
|
|
40
40
|
color: var(--a-fg);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/* Safari 17.x bug: `:scope:hover` inside `@scope` doesn't match the scope
|
|
44
|
+
root. Plain selectors outside the @scope work. `:focus-visible` matches
|
|
45
|
+
correctly inside @scope, so the combined `:hover, :focus-visible` rule
|
|
46
|
+
is split — `:hover` moves out, `:focus-visible` stays. The
|
|
47
|
+
`:scope[variant="danger"]:hover` rules also move (same bug shape). See
|
|
48
|
+
docs/BROWSER-COMPAT.md §3a. */
|
|
49
|
+
menu-item-ui:hover {
|
|
50
|
+
--menu-item-bg: var(--menu-item-bg-hover);
|
|
51
|
+
--menu-item-fg: var(--menu-item-fg-hover);
|
|
52
|
+
outline: none;
|
|
53
|
+
}
|
|
54
|
+
menu-item-ui:hover [slot="icon"] {
|
|
55
|
+
color: var(--menu-item-icon-fg-hover);
|
|
56
|
+
}
|
|
57
|
+
menu-item-ui[variant="danger"]:hover {
|
|
58
|
+
--menu-item-bg: var(--menu-item-danger-bg);
|
|
59
|
+
--menu-item-fg: var(--menu-item-danger-fg);
|
|
60
|
+
}
|
|
61
|
+
menu-item-ui[variant="danger"]:hover [slot="icon"] {
|
|
62
|
+
color: var(--menu-item-danger-fg);
|
|
63
|
+
}
|
|
64
|
+
|
|
43
65
|
@scope (menu-item-ui) {
|
|
44
66
|
:where(:scope) {
|
|
45
67
|
/* ── Layout ── */
|
|
@@ -84,7 +106,6 @@ menu-ui [data-menu-popover] {
|
|
|
84
106
|
color var(--menu-item-duration) var(--menu-item-easing);
|
|
85
107
|
}
|
|
86
108
|
|
|
87
|
-
:scope:hover,
|
|
88
109
|
:scope:focus-visible {
|
|
89
110
|
--menu-item-bg: var(--menu-item-bg-hover);
|
|
90
111
|
--menu-item-fg: var(--menu-item-fg-hover);
|
|
@@ -98,9 +119,6 @@ menu-ui [data-menu-popover] {
|
|
|
98
119
|
color: var(--menu-item-icon-fg);
|
|
99
120
|
transition: color var(--menu-item-duration) var(--menu-item-easing);
|
|
100
121
|
}
|
|
101
|
-
:scope:hover [slot="icon"] {
|
|
102
|
-
color: var(--menu-item-icon-fg-hover);
|
|
103
|
-
}
|
|
104
122
|
|
|
105
123
|
/* Text */
|
|
106
124
|
[slot="text"] {
|
|
@@ -112,16 +130,9 @@ menu-ui [data-menu-popover] {
|
|
|
112
130
|
:scope[variant="danger"] {
|
|
113
131
|
--menu-item-fg: var(--a-danger-bg);
|
|
114
132
|
}
|
|
115
|
-
:scope[variant="danger"]:hover {
|
|
116
|
-
--menu-item-bg: var(--menu-item-danger-bg);
|
|
117
|
-
--menu-item-fg: var(--menu-item-danger-fg);
|
|
118
|
-
}
|
|
119
133
|
:scope[variant="danger"] [slot="icon"] {
|
|
120
134
|
color: var(--menu-item-danger-fg);
|
|
121
135
|
}
|
|
122
|
-
:scope[variant="danger"]:hover [slot="icon"] {
|
|
123
|
-
color: var(--menu-item-danger-fg);
|
|
124
|
-
}
|
|
125
136
|
|
|
126
137
|
/* ── Disabled ── */
|
|
127
138
|
:scope[disabled] {
|
|
@@ -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,3 +1,33 @@
|
|
|
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
|
+
option-card-ui:not([checked]):not([disabled]):hover {
|
|
5
|
+
background: var(--option-card-bg-hover);
|
|
6
|
+
border-color: var(--option-card-border-hover);
|
|
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
|
+
}
|
|
30
|
+
|
|
1
31
|
@scope (option-card-ui) {
|
|
2
32
|
:where(:scope) {
|
|
3
33
|
/* ── Container ── */
|
|
@@ -134,43 +164,9 @@
|
|
|
134
164
|
:scope:has(> [slot="icon"]) > :not([slot]) {
|
|
135
165
|
grid-column: 3 / -1;
|
|
136
166
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
/* ── State: hover (not checked, not disabled) ── */
|
|
142
|
-
:scope:not([checked]):not([disabled]):hover {
|
|
143
|
-
background: var(--option-card-bg-hover);
|
|
144
|
-
border-color: var(--option-card-border-hover);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/* ── State: checked — accent border + tinted bg + filled radio.
|
|
148
|
-
The indicator becomes an accent disc with a centered dot of
|
|
149
|
-
--option-card-radio-dot at 60% of the size, mirroring
|
|
150
|
-
radio-ui's recipe (radio.css:75-78). Done with a radial
|
|
151
|
-
gradient so a single pseudo-element carries both layers. */
|
|
152
|
-
:scope[checked] {
|
|
153
|
-
background: var(--option-card-bg-checked);
|
|
154
|
-
border-color: var(--option-card-border-checked);
|
|
155
|
-
}
|
|
156
|
-
:scope[checked]::before {
|
|
157
|
-
border-color: var(--option-card-radio-fill);
|
|
158
|
-
background:
|
|
159
|
-
radial-gradient(
|
|
160
|
-
circle,
|
|
161
|
-
var(--option-card-radio-dot) 0 30%,
|
|
162
|
-
var(--option-card-radio-fill) 30% 100%
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
/* Heading + icon shift to a strong color when checked — gives the
|
|
166
|
-
selected card a clear text-level emphasis on top of the bg/border
|
|
167
|
-
state, so picking is unambiguous beyond the radio dot alone. */
|
|
168
|
-
:scope[checked] > [slot="heading"] {
|
|
169
|
-
color: var(--option-card-heading-color-checked);
|
|
170
|
-
}
|
|
171
|
-
:scope[checked] > [slot="icon"] {
|
|
172
|
-
color: var(--option-card-icon-color-checked);
|
|
173
|
-
}
|
|
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. */
|
|
174
170
|
|
|
175
171
|
/* ── Layout: tile — icon top-left, indicator top-right, heading +
|
|
176
172
|
description below, all left-aligned. Used for hero pickers
|
|
@@ -1,3 +1,24 @@
|
|
|
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. */
|
|
5
|
+
radio-ui:not([disabled]):hover [slot="dot"] {
|
|
6
|
+
border-color: var(--radio-border-hover);
|
|
7
|
+
background: var(--radio-bg-hover);
|
|
8
|
+
}
|
|
9
|
+
radio-ui[checked]:not([disabled]):hover [slot="dot"] {
|
|
10
|
+
background: var(--radio-bg-checked-hover);
|
|
11
|
+
border-color: var(--radio-bg-checked-hover);
|
|
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
|
+
}
|
|
21
|
+
|
|
1
22
|
@scope (radio-ui) {
|
|
2
23
|
:where(:scope) {
|
|
3
24
|
/* ── Layout ── (size scales with universal [size] attribute via --a-toggle-size) */
|
|
@@ -72,25 +93,7 @@
|
|
|
72
93
|
height var(--radio-duration) var(--radio-easing);
|
|
73
94
|
}
|
|
74
95
|
|
|
75
|
-
|
|
76
|
-
width: calc(var(--radio-size) * 0.6);
|
|
77
|
-
height: calc(var(--radio-size) * 0.6);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
:scope:not([disabled]):hover [slot="dot"] {
|
|
81
|
-
border-color: var(--radio-border-hover);
|
|
82
|
-
background: var(--radio-bg-hover);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
:scope[checked] [slot="dot"] {
|
|
86
|
-
background: var(--radio-bg-checked);
|
|
87
|
-
border-color: var(--radio-border-checked);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
:scope[checked]:not([disabled]):hover [slot="dot"] {
|
|
91
|
-
background: var(--radio-bg-checked-hover);
|
|
92
|
-
border-color: var(--radio-bg-checked-hover);
|
|
93
|
-
}
|
|
96
|
+
/* hover + [checked] rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
94
97
|
|
|
95
98
|
/* Label */
|
|
96
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,3 +1,10 @@
|
|
|
1
|
+
/* Safari 17.x bug: `:scope:hover` inside `@scope` doesn't match the scope
|
|
2
|
+
root. Plain selector outside the @scope works. See
|
|
3
|
+
docs/BROWSER-COMPAT.md §3a. */
|
|
4
|
+
rating-ui:hover [data-rating-symbol] {
|
|
5
|
+
color: var(--rating-fg-hover);
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
@scope (rating-ui) {
|
|
2
9
|
:where(:scope) {
|
|
3
10
|
/* ── Layout ── */
|
|
@@ -72,10 +79,6 @@
|
|
|
72
79
|
clip-path: inset(0 0 0 0);
|
|
73
80
|
}
|
|
74
81
|
|
|
75
|
-
:scope:hover [data-rating-symbol] {
|
|
76
|
-
color: var(--rating-fg-hover);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
82
|
/* ── Variants override TOKENS only ── */
|
|
80
83
|
:scope[variant="accent"] {
|
|
81
84
|
--rating-fg-filled: var(--a-accent-bg);
|
|
@@ -1,3 +1,13 @@
|
|
|
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
|
+
segment-ui:not([disabled]):not([selected]):hover {
|
|
5
|
+
color: var(--segment-fg-hover);
|
|
6
|
+
}
|
|
7
|
+
segment-ui[selected] {
|
|
8
|
+
color: var(--segment-fg-selected);
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
@scope (segment-ui) {
|
|
2
12
|
:where(:scope) {
|
|
3
13
|
/* ── Layout ── */
|
|
@@ -73,14 +83,7 @@
|
|
|
73
83
|
white-space: nowrap;
|
|
74
84
|
}
|
|
75
85
|
|
|
76
|
-
/* States */
|
|
77
|
-
:scope:not([disabled]):not([selected]):hover {
|
|
78
|
-
color: var(--segment-fg-hover);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
:scope[selected] {
|
|
82
|
-
color: var(--segment-fg-selected);
|
|
83
|
-
}
|
|
86
|
+
/* States — hover + [selected] rules moved outside @scope; see Safari 17.x bug note at top. */
|
|
84
87
|
|
|
85
88
|
:scope:focus-visible {
|
|
86
89
|
outline: none;
|
|
@@ -1,3 +1,23 @@
|
|
|
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. */
|
|
4
|
+
switch-ui:not([disabled]):hover {
|
|
5
|
+
--switch-track-bg: var(--switch-track-bg-hover);
|
|
6
|
+
--switch-track-border: var(--switch-track-border-hover);
|
|
7
|
+
}
|
|
8
|
+
switch-ui[checked]:not([disabled]):hover {
|
|
9
|
+
--switch-track-bg: var(--switch-track-bg-checked-hover);
|
|
10
|
+
--switch-track-border: var(--switch-track-border-checked-hover);
|
|
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
|
+
}
|
|
20
|
+
|
|
1
21
|
@scope (switch-ui) {
|
|
2
22
|
:where(:scope) {
|
|
3
23
|
/* ── Layout ── */
|
|
@@ -66,19 +86,7 @@
|
|
|
66
86
|
background var(--switch-duration) var(--switch-easing),
|
|
67
87
|
border-color var(--switch-duration) var(--switch-easing);
|
|
68
88
|
}
|
|
69
|
-
|
|
70
|
-
--switch-track-bg: var(--switch-track-bg-hover);
|
|
71
|
-
--switch-track-border: var(--switch-track-border-hover);
|
|
72
|
-
}
|
|
73
|
-
:scope[checked] {
|
|
74
|
-
--switch-track-bg: var(--switch-track-bg-checked);
|
|
75
|
-
--switch-track-border: var(--switch-track-border-checked);
|
|
76
|
-
--switch-thumb-bg: var(--switch-thumb-bg-checked);
|
|
77
|
-
}
|
|
78
|
-
:scope[checked]:not([disabled]):hover {
|
|
79
|
-
--switch-track-bg: var(--switch-track-bg-checked-hover);
|
|
80
|
-
--switch-track-border: var(--switch-track-border-checked-hover);
|
|
81
|
-
}
|
|
89
|
+
/* hover + [checked] rules moved outside @scope — see Safari 17.x bug note at top. */
|
|
82
90
|
|
|
83
91
|
[slot="thumb"] {
|
|
84
92
|
position: absolute;
|
|
@@ -93,9 +101,7 @@
|
|
|
93
101
|
transform var(--switch-duration) var(--switch-easing),
|
|
94
102
|
background var(--switch-duration) var(--switch-easing);
|
|
95
103
|
}
|
|
96
|
-
:scope[checked] [slot="thumb"]
|
|
97
|
-
transform: translateX(var(--switch-thumb-travel));
|
|
98
|
-
}
|
|
104
|
+
/* :scope[checked] [slot="thumb"] moved outside @scope — see Safari 17.x bug note at top. */
|
|
99
105
|
|
|
100
106
|
[slot="label"] { font-size: var(--switch-font-size); }
|
|
101
107
|
|
package/components/tag/tag.css
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/* Safari 17.x bug: `:scope[attr]:hover` inside `@scope` doesn't match the
|
|
2
|
+
scope root. Plain selector outside works. See docs/BROWSER-COMPAT.md §3a. */
|
|
3
|
+
tag-ui[removable]:not([disabled]):hover {
|
|
4
|
+
--tag-bg: var(--tag-bg-hover);
|
|
5
|
+
}
|
|
6
|
+
|
|
1
7
|
@scope (tag-ui) {
|
|
2
8
|
:where(:scope) {
|
|
3
9
|
/* ── Tokens ── */
|
|
@@ -75,10 +81,7 @@
|
|
|
75
81
|
|
|
76
82
|
/* Size handled by universal [size] attribute system. */
|
|
77
83
|
|
|
78
|
-
/*
|
|
79
|
-
:scope[removable]:not([disabled]):hover {
|
|
80
|
-
--tag-bg: var(--tag-bg-hover);
|
|
81
|
-
}
|
|
84
|
+
/* hover rule moved outside @scope — see Safari 17.x bug note at top. */
|
|
82
85
|
|
|
83
86
|
/* ── Focus ── */
|
|
84
87
|
:scope:focus-visible {
|
|
@@ -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,3 +1,12 @@
|
|
|
1
|
+
/* Safari 17.x bug: `:scope:not(...):hover` inside `@scope` doesn't match
|
|
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 {
|
|
6
|
+
--toggle-option-bg: var(--toggle-option-bg-hover);
|
|
7
|
+
--toggle-option-fg: var(--toggle-option-fg-hover);
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
@scope (toggle-group-ui) {
|
|
2
11
|
:where(:scope) {
|
|
3
12
|
/* ── Tokens ── */
|
|
@@ -69,10 +78,7 @@
|
|
|
69
78
|
border-inline-start: var(--toggle-option-border-width) solid var(--toggle-option-border-color);
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
|
|
73
|
-
--toggle-option-bg: var(--toggle-option-bg-hover);
|
|
74
|
-
--toggle-option-fg: var(--toggle-option-fg-hover);
|
|
75
|
-
}
|
|
81
|
+
/* hover rule moved outside @scope — see Safari 17.x bug note at top. */
|
|
76
82
|
|
|
77
83
|
:scope:focus-visible {
|
|
78
84
|
outline: none;
|