maverick-wave 5.38.0 → 6.0.0
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/README.md +63 -47
- package/maverick-wave.min.css +94 -68
- package/maverick-wave.min.js +1 -1
- package/package.json +7 -7
- package/src/js/main.js +382 -57
- package/src/scss/abstracts/_mixins.scss +35 -24
- package/src/scss/abstracts/_variables.scss +15 -0
- package/src/scss/base/_base.scss +107 -64
- package/src/scss/base/_index.scss +1 -0
- package/src/scss/base/_page-transitions.scss +29 -0
- package/src/scss/base/_reset.scss +0 -8
- package/src/scss/components/_accordions.scss +23 -18
- package/src/scss/components/_action-bar.scss +143 -0
- package/src/scss/components/_alerts.scss +13 -1
- package/src/scss/components/_avatars.scss +17 -0
- package/src/scss/components/_badge.scss +12 -0
- package/src/scss/components/_breadcrumbs.scss +10 -2
- package/src/scss/components/_chat.scss +250 -0
- package/src/scss/components/_code.scss +3 -1
- package/src/scss/components/_compare.scss +135 -0
- package/src/scss/components/_deck.scss +8 -14
- package/src/scss/components/_devices.scss +323 -0
- package/src/scss/components/_dropdown.scss +43 -2
- package/src/scss/components/_empty-state.scss +43 -0
- package/src/scss/components/_flag.scss +16 -0
- package/src/scss/components/_index.scss +6 -0
- package/src/scss/components/_lightbox.scss +1 -1
- package/src/scss/components/_marquee.scss +132 -0
- package/src/scss/components/_modals.scss +112 -83
- package/src/scss/components/_occasions.scss +62 -11
- package/src/scss/components/_pagination.scss +91 -0
- package/src/scss/components/_portrait-gallery.scss +1 -1
- package/src/scss/components/_progress.scss +122 -2
- package/src/scss/components/_segmented.scss +65 -2
- package/src/scss/components/_skeleton.scss +8 -0
- package/src/scss/components/_spinners.scss +38 -0
- package/src/scss/components/_stat.scss +232 -0
- package/src/scss/components/_stepper.scss +42 -2
- package/src/scss/components/_stories.scss +36 -22
- package/src/scss/components/_tables.scss +160 -17
- package/src/scss/components/_tabs.scss +42 -4
- package/src/scss/components/_tags.scss +39 -4
- package/src/scss/components/_tiles.scss +1 -1
- package/src/scss/components/_timelines.scss +138 -1
- package/src/scss/components/_toasts.scss +5 -1
- package/src/scss/components/_tooltip.scss +13 -0
- package/src/scss/form-elements/_checkbox.scss +40 -7
- package/src/scss/form-elements/_form.scss +2 -4
- package/src/scss/form-elements/_input.scss +9 -6
- package/src/scss/form-elements/_radio.scss +32 -3
- package/src/scss/form-elements/_select.scss +44 -1
- package/src/scss/form-elements/_slider.scss +18 -0
- package/src/scss/form-elements/_textarea.scss +9 -6
- package/src/scss/form-elements/_toggle.scss +37 -4
- package/src/scss/layout/_app-shell.scss +661 -0
- package/src/scss/layout/_bento.scss +43 -0
- package/src/scss/layout/_footer.scss +114 -2
- package/src/scss/layout/_grid.scss +7 -2
- package/src/scss/layout/_header-reveal.scss +30 -17
- package/src/scss/layout/_header.scss +21 -4
- package/src/scss/layout/_index.scss +2 -0
- package/src/scss/layout/_parallax.scss +13 -11
- package/src/scss/utilities/_accessibility.scss +4 -19
- package/src/scss/utilities/_index.scss +1 -0
- package/src/scss/utilities/_print.scss +7 -3
- package/src/scss/utilities/_reveal.scss +25 -17
- package/src/scss/utilities/_shape.scss +24 -0
- package/src/scss/utilities/_touch-targets.scss +23 -0
- package/src/scss/utilities/_variants.scss +25 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@use 'sass:map';
|
|
2
|
+
@use 'sass:selector';
|
|
2
3
|
@use 'sass:math';
|
|
3
4
|
@use 'variables' as v;
|
|
4
5
|
@use 'functions' as *;
|
|
@@ -109,6 +110,19 @@
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
// Out of sight, still read by a screen reader
|
|
114
|
+
@mixin visually-hidden {
|
|
115
|
+
position: absolute;
|
|
116
|
+
width: 1px;
|
|
117
|
+
height: 1px;
|
|
118
|
+
padding: 0;
|
|
119
|
+
margin: -1px;
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
clip-path: inset(50%);
|
|
122
|
+
white-space: nowrap;
|
|
123
|
+
border: 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
112
126
|
// Without the `min-width: 0` that mw-text-truncate carries: that fixes the layout
|
|
113
127
|
// around the text, and handing it to seven components would change how they size
|
|
114
128
|
@mixin truncate {
|
|
@@ -127,6 +141,26 @@
|
|
|
127
141
|
}
|
|
128
142
|
}
|
|
129
143
|
|
|
144
|
+
// Motion the OS and `mw-motion-off` both allow; unify() merges a leading :root
|
|
145
|
+
@mixin motion-safe {
|
|
146
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
147
|
+
@at-root #{selector.unify(&, ':root:not(.mw-motion-off) *')} {
|
|
148
|
+
@content;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// The other side of the same switch
|
|
154
|
+
@mixin motion-reduced {
|
|
155
|
+
@media (prefers-reduced-motion: reduce) {
|
|
156
|
+
@content;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@at-root #{selector.unify(&, ':root.mw-motion-off *')} {
|
|
160
|
+
@content;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
130
164
|
// A hover that *travels*. Separate from `hover`, because movement has two more
|
|
131
165
|
// opt-outs than a colour change does: reduced motion, where a transform still
|
|
132
166
|
// jumps to its end position in one frame however short the duration is, and the
|
|
@@ -138,7 +172,7 @@
|
|
|
138
172
|
// and a label that lands where it belongs beats two pixels of travel.
|
|
139
173
|
@mixin hover-move {
|
|
140
174
|
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
|
|
141
|
-
:root:not(.mw-hover-static) &:hover:not([data-tooltip]) {
|
|
175
|
+
:root:not(.mw-hover-static, .mw-motion-off) &:hover:not([data-tooltip]) {
|
|
142
176
|
@content;
|
|
143
177
|
}
|
|
144
178
|
}
|
|
@@ -200,29 +234,6 @@
|
|
|
200
234
|
scrollbar-width: thin;
|
|
201
235
|
// Firefox needs both values - a single one is invalid and drops the declaration
|
|
202
236
|
scrollbar-color: #{$thumb} #{$track};
|
|
203
|
-
|
|
204
|
-
&::-webkit-scrollbar {
|
|
205
|
-
width: 8px;
|
|
206
|
-
height: 8px;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
&::-webkit-scrollbar-track {
|
|
210
|
-
background: #{$track};
|
|
211
|
-
border-radius: 4px;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
&::-webkit-scrollbar-thumb {
|
|
215
|
-
background: #{$thumb};
|
|
216
|
-
border-radius: 4px;
|
|
217
|
-
|
|
218
|
-
&:hover {
|
|
219
|
-
background: var(--mw-primary-text-color);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
&::-webkit-scrollbar-corner {
|
|
224
|
-
background: #{$track};
|
|
225
|
-
}
|
|
226
237
|
}
|
|
227
238
|
|
|
228
239
|
// A hairline of light along the top edge and a shadow underneath, as if the light
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
$mw-theme-mode: 'switchable' !default; // 'dark', 'light', or 'switchable'
|
|
5
5
|
|
|
6
|
+
// Opt-in, because a page only crossfades into one that carries the rule too
|
|
7
|
+
$mw-page-transitions: false !default;
|
|
8
|
+
|
|
6
9
|
$mw-hero-image: url('https://images.unsplash.com/photo-1591638462868-19cfad9c49d1?q=80&w=1300&auto=format&fit=crop') !default;
|
|
7
10
|
|
|
8
11
|
// A second, flatter layer over the image - see mw-parallax-pattern. Fine lines
|
|
@@ -292,6 +295,13 @@ $base-colors: (
|
|
|
292
295
|
'section-alternate-pattern': fade('gray-color', 30%),
|
|
293
296
|
'form-elements-background': $form-elements-background,
|
|
294
297
|
'form-elements-color': shade('light-text-color', 18%),
|
|
298
|
+
// Opaque and alike in both themes; readonly keeps full ink, disabled mutes it
|
|
299
|
+
'form-elements-readonly-background': string.unquote(
|
|
300
|
+
'color-mix(in oklab, var(--mw-form-elements-background) 70%, var(--mw-gray-color))'
|
|
301
|
+
),
|
|
302
|
+
'form-elements-disabled-background': string.unquote(
|
|
303
|
+
'color-mix(in oklab, var(--mw-form-elements-background) 70%, var(--mw-gray-color))'
|
|
304
|
+
),
|
|
295
305
|
);
|
|
296
306
|
|
|
297
307
|
// Status colors. Every status offers the same four tones.
|
|
@@ -525,6 +535,8 @@ $z-index: (
|
|
|
525
535
|
'lift': 3,
|
|
526
536
|
'card': 10,
|
|
527
537
|
'menu': 30,
|
|
538
|
+
// Over the page and its menus, under the open navigation's scrim
|
|
539
|
+
'action-bar': 98,
|
|
528
540
|
// The scrim sits under the bar, the panel hangs off it, the logo clears the
|
|
529
541
|
// panel and the burger stays on top of all of them while it is the X.
|
|
530
542
|
'header-scrim': 99,
|
|
@@ -540,6 +552,9 @@ $z-index: (
|
|
|
540
552
|
'occasion': 1000,
|
|
541
553
|
);
|
|
542
554
|
|
|
555
|
+
// Native, ARIA, and Angular's classes for a validator that lives in TypeScript
|
|
556
|
+
$invalid-states: ':user-invalid, [aria-invalid="true"], .ng-invalid.ng-touched';
|
|
557
|
+
|
|
543
558
|
// Native select arrow, drawn as a background layer because `appearance: none`
|
|
544
559
|
// removes the OS one. Shared, because any control that adds a second
|
|
545
560
|
// background layer (see `.mw-prefilled`) has to restate the whole list.
|
package/src/scss/base/_base.scss
CHANGED
|
@@ -107,12 +107,13 @@
|
|
|
107
107
|
|
|
108
108
|
// The only way the chrome the browser draws itself follows the theme:
|
|
109
109
|
// scrollbars, the select popup, the date picker panel, number spinners.
|
|
110
|
-
// Under `switchable`
|
|
111
|
-
// does double duty and the @supports block widens it to `light dark`.
|
|
110
|
+
// Under `switchable` it is also what every light-dark() token reads.
|
|
112
111
|
@if $mw-theme-mode == 'light' {
|
|
113
112
|
color-scheme: light;
|
|
114
|
-
} @else {
|
|
113
|
+
} @else if $mw-theme-mode == 'dark' {
|
|
115
114
|
color-scheme: dark;
|
|
115
|
+
} @else {
|
|
116
|
+
color-scheme: light dark;
|
|
116
117
|
}
|
|
117
118
|
// Native controls the framework does not paint over take the brand, not OS blue
|
|
118
119
|
accent-color: var(--mw-primary-color);
|
|
@@ -202,68 +203,44 @@
|
|
|
202
203
|
}
|
|
203
204
|
|
|
204
205
|
@if $mw-theme-mode == 'switchable' {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
// A custom property holding light-dark() is resolved where it is *used*,
|
|
207
|
+
// against that element's color-scheme - so one declaration on :root serves
|
|
208
|
+
// both themes, and a class further down switches every token by changing
|
|
209
|
+
// nothing but the scheme. The page also follows the OS before any script.
|
|
210
|
+
:root {
|
|
211
|
+
@each $name, $value in $_theme-colors {
|
|
212
|
+
--mw-#{$name}: light-dark(
|
|
213
|
+
var(--mw-light-#{$name}),
|
|
214
|
+
var(--mw-dark-#{$name})
|
|
215
|
+
);
|
|
209
216
|
}
|
|
210
|
-
|
|
211
|
-
color-scheme: light;
|
|
212
217
|
}
|
|
213
218
|
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
// class further down switches every token by changing nothing but the
|
|
218
|
-
// scheme. The page then also follows the OS out of the box, which the
|
|
219
|
-
// class-only route could never do: before the script had run, a machine set
|
|
220
|
-
// to light still got the dark theme for a frame.
|
|
221
|
-
//
|
|
222
|
-
// The block above stays as the fallback for Chrome 119-122 and Safari
|
|
223
|
-
// 16.4-17.4, which are inside the declared browserslist but predate
|
|
224
|
-
// light-dark(). Drop it, and the two class rules with it, once the support
|
|
225
|
-
// floor moves past Chrome 123 / Safari 17.5.
|
|
226
|
-
@supports (color: light-dark(#000, #fff)) {
|
|
227
|
-
:root,
|
|
228
|
-
.mw-theme-light {
|
|
229
|
-
@each $name, $value in $_theme-colors {
|
|
230
|
-
--mw-#{$name}: light-dark(
|
|
231
|
-
var(--mw-light-#{$name}),
|
|
232
|
-
var(--mw-dark-#{$name})
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
219
|
+
// Not a color, so it cannot ride along above - it follows the OS here and
|
|
220
|
+
// is overridden by whichever class the toggle puts on <html>
|
|
221
|
+
@media (prefers-color-scheme: light) {
|
|
237
222
|
:root {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// Not a color, so it cannot ride along above - it follows the OS here and
|
|
242
|
-
// is overridden by whichever class the toggle puts on the body
|
|
243
|
-
@media (prefers-color-scheme: light) {
|
|
244
|
-
:root {
|
|
245
|
-
@each $name in $theme-non-colors {
|
|
246
|
-
--mw-#{$name}: var(--mw-light-#{$name});
|
|
247
|
-
}
|
|
223
|
+
@each $name in $theme-non-colors {
|
|
224
|
+
--mw-#{$name}: var(--mw-light-#{$name});
|
|
248
225
|
}
|
|
249
226
|
}
|
|
227
|
+
}
|
|
250
228
|
|
|
251
|
-
|
|
252
|
-
|
|
229
|
+
.mw-theme-light {
|
|
230
|
+
color-scheme: light;
|
|
253
231
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
232
|
+
@each $name in $theme-non-colors {
|
|
233
|
+
--mw-#{$name}: var(--mw-light-#{$name});
|
|
257
234
|
}
|
|
235
|
+
}
|
|
258
236
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
237
|
+
// Only reachable once the OS says light: the explicit counterpart to the
|
|
238
|
+
// class above, so a reader who wants dark on a light machine gets it
|
|
239
|
+
.mw-theme-dark {
|
|
240
|
+
color-scheme: dark;
|
|
263
241
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
242
|
+
@each $name in $theme-non-colors {
|
|
243
|
+
--mw-#{$name}: var(--mw-dark-#{$name});
|
|
267
244
|
}
|
|
268
245
|
}
|
|
269
246
|
}
|
|
@@ -294,23 +271,31 @@
|
|
|
294
271
|
// The duration tokens cover everything built on them, the blanket rule below
|
|
295
272
|
// the few animations that name their own timing. 1ms and not 0: a zero-length
|
|
296
273
|
// transition never fires transitionend, and a script waiting for it would hang.
|
|
274
|
+
@mixin _still-tokens {
|
|
275
|
+
--mw-duration-instant: 1ms;
|
|
276
|
+
--mw-duration-fast: 1ms;
|
|
277
|
+
--mw-duration-base: 1ms;
|
|
278
|
+
--mw-duration-slow: 1ms;
|
|
279
|
+
--mw-duration-slower: 1ms;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@mixin _still-everything {
|
|
283
|
+
animation-duration: 1ms !important;
|
|
284
|
+
animation-delay: 0ms !important;
|
|
285
|
+
animation-iteration-count: 1 !important;
|
|
286
|
+
transition-duration: 1ms !important;
|
|
287
|
+
transition-delay: 0ms !important;
|
|
288
|
+
}
|
|
289
|
+
|
|
297
290
|
@media (prefers-reduced-motion: reduce) {
|
|
298
291
|
:root {
|
|
299
|
-
|
|
300
|
-
--mw-duration-fast: 1ms;
|
|
301
|
-
--mw-duration-base: 1ms;
|
|
302
|
-
--mw-duration-slow: 1ms;
|
|
303
|
-
--mw-duration-slower: 1ms;
|
|
292
|
+
@include _still-tokens;
|
|
304
293
|
}
|
|
305
294
|
|
|
306
295
|
*,
|
|
307
296
|
*::before,
|
|
308
297
|
*::after {
|
|
309
|
-
|
|
310
|
-
animation-delay: 0ms !important;
|
|
311
|
-
animation-iteration-count: 1 !important;
|
|
312
|
-
transition-duration: 1ms !important;
|
|
313
|
-
transition-delay: 0ms !important;
|
|
298
|
+
@include _still-everything;
|
|
314
299
|
}
|
|
315
300
|
|
|
316
301
|
html {
|
|
@@ -318,6 +303,18 @@
|
|
|
318
303
|
}
|
|
319
304
|
}
|
|
320
305
|
|
|
306
|
+
// The same switch, thrown by the page instead of the OS
|
|
307
|
+
:root.mw-motion-off {
|
|
308
|
+
@include _still-tokens;
|
|
309
|
+
scroll-behavior: auto;
|
|
310
|
+
|
|
311
|
+
*,
|
|
312
|
+
*::before,
|
|
313
|
+
*::after {
|
|
314
|
+
@include _still-everything;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
321
318
|
// Without this a theme flip starts ~5900 concurrent transitions at once
|
|
322
319
|
.mw-theme-switching,
|
|
323
320
|
.mw-theme-switching *,
|
|
@@ -326,3 +323,49 @@
|
|
|
326
323
|
transition: none !important;
|
|
327
324
|
}
|
|
328
325
|
}
|
|
326
|
+
|
|
327
|
+
@layer mw.base {
|
|
328
|
+
// The dark-*/light-* sources: the theme aliases read them, so both themes follow
|
|
329
|
+
@media (prefers-contrast: more) {
|
|
330
|
+
:root {
|
|
331
|
+
--mw-dark-border: #{fade('dark-text-color', 55%)};
|
|
332
|
+
--mw-light-border: #{fade('light-text-color', 55%)};
|
|
333
|
+
--mw-dark-border-accent: var(--mw-dark-primary-text-color);
|
|
334
|
+
--mw-light-border-accent: var(--mw-light-primary-text-color);
|
|
335
|
+
--mw-light-corner-accent: var(--mw-light-primary-text-color);
|
|
336
|
+
--mw-dark-text-muted-color: #{muted(0.82)};
|
|
337
|
+
--mw-light-text-muted-color: #{muted(0.4)};
|
|
338
|
+
--mw-focus-ring-width: 3px;
|
|
339
|
+
|
|
340
|
+
// 4.5:1 on a card instead of the 3:1 the default ink is tuned to
|
|
341
|
+
@each $name
|
|
342
|
+
in ('primary', 'secondary', 'success', 'warning', 'danger', 'info')
|
|
343
|
+
{
|
|
344
|
+
--mw-dark-#{$name}-text-color: #{ink-on-dark('#{$name}-color', 0.66)};
|
|
345
|
+
--mw-light-#{$name}-text-color: oklch(
|
|
346
|
+
from var(--mw-#{$name}-color) min(l, 0.45) c h
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Text on a see-through fill only - the hero's backdrop-filter is brightness
|
|
353
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
354
|
+
.mw-announcement,
|
|
355
|
+
.mw-hero-badge,
|
|
356
|
+
.mw-container:has(.mw-hero) .mw-btn-outline:not(:hover) {
|
|
357
|
+
backdrop-filter: none !important;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.mw-announcement {
|
|
361
|
+
background: var(--mw-primary-color) !important;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.mw-hero-badge,
|
|
365
|
+
.mw-container:has(.mw-hero) .mw-btn-outline:not(:hover) {
|
|
366
|
+
background: oklch(
|
|
367
|
+
from var(--mw-hero-text-color) calc(1 - l) 0 h
|
|
368
|
+
) !important;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@use '../abstracts' as *;
|
|
2
|
+
|
|
3
|
+
@if $mw-page-transitions {
|
|
4
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
5
|
+
@view-transition {
|
|
6
|
+
navigation: auto;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@layer mw.base {
|
|
11
|
+
::view-transition-old(root),
|
|
12
|
+
::view-transition-new(root) {
|
|
13
|
+
animation-duration: var(--mw-duration-slow);
|
|
14
|
+
animation-timing-function: var(--mw-ease-in-out);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// mw-motion-off cannot reach the at-rule above, so the pages swap unfaded
|
|
18
|
+
:root.mw-motion-off::view-transition-group(*),
|
|
19
|
+
:root.mw-motion-off::view-transition-old(*),
|
|
20
|
+
:root.mw-motion-off::view-transition-new(*) {
|
|
21
|
+
animation-name: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Its own group, so the bar stands still while the page under it fades
|
|
25
|
+
.mw-header {
|
|
26
|
+
view-transition-name: mw-header;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -31,14 +31,6 @@
|
|
|
31
31
|
overflow-wrap: break-word;
|
|
32
32
|
-webkit-font-smoothing: antialiased;
|
|
33
33
|
-moz-osx-font-smoothing: grayscale;
|
|
34
|
-
|
|
35
|
-
// `dvh` and not `vh`: on iOS `100vh` is the tall viewport behind the
|
|
36
|
-
// address bar, so the locked body stays taller than the screen and keeps a
|
|
37
|
-
// strip of rubber-band scroll under the modal.
|
|
38
|
-
&:has(.mw-modal-open) {
|
|
39
|
-
overflow: hidden;
|
|
40
|
-
height: 100dvh;
|
|
41
|
-
}
|
|
42
34
|
}
|
|
43
35
|
|
|
44
36
|
// The UA rule behind the `hidden` attribute is `[hidden] { display: none }`, and
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
@use '../abstracts' as *;
|
|
2
2
|
|
|
3
3
|
@layer mw.components {
|
|
4
|
+
// aria-expanded on the header opens it too, for markup an application renders
|
|
5
|
+
@mixin _open-header {
|
|
6
|
+
@include active {
|
|
7
|
+
@content;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&[aria-expanded='true'] {
|
|
11
|
+
@content;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@mixin _open-content {
|
|
16
|
+
@include active {
|
|
17
|
+
@content;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@at-root .mw-accordion-header[aria-expanded='true'] + #{&} {
|
|
21
|
+
@content;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
4
25
|
.mw-accordion {
|
|
5
26
|
border: 1px solid var(--mw-border);
|
|
6
27
|
@include surface;
|
|
@@ -73,7 +94,7 @@
|
|
|
73
94
|
transform: rotate(0deg);
|
|
74
95
|
}
|
|
75
96
|
|
|
76
|
-
@include
|
|
97
|
+
@include _open-header {
|
|
77
98
|
background: var(--mw-primary-color);
|
|
78
99
|
color: var(--mw-primary-accent-text-color);
|
|
79
100
|
|
|
@@ -113,7 +134,7 @@
|
|
|
113
134
|
}
|
|
114
135
|
}
|
|
115
136
|
|
|
116
|
-
@include
|
|
137
|
+
@include _open-content {
|
|
117
138
|
grid-template-rows: 1fr;
|
|
118
139
|
max-height: 500px;
|
|
119
140
|
overflow-y: auto;
|
|
@@ -123,24 +144,8 @@
|
|
|
123
144
|
border-top-width: 1px;
|
|
124
145
|
}
|
|
125
146
|
|
|
126
|
-
// Both spellings: the standard pair is what Firefox reads, the webkit
|
|
127
|
-
// pseudos are for Safari below 18.2.
|
|
128
147
|
scrollbar-width: thin;
|
|
129
148
|
scrollbar-color: var(--mw-primary-color-hover) var(--mw-card-background);
|
|
130
|
-
|
|
131
|
-
&::-webkit-scrollbar {
|
|
132
|
-
width: 6px;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
&::-webkit-scrollbar-track {
|
|
136
|
-
background: var(--mw-card-background);
|
|
137
|
-
border-radius: radius('sm');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
&::-webkit-scrollbar-thumb {
|
|
141
|
-
background: var(--mw-primary-color-hover);
|
|
142
|
-
border-radius: radius('sm');
|
|
143
|
-
}
|
|
144
149
|
}
|
|
145
150
|
}
|
|
146
151
|
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
@use '../abstracts' as *;
|
|
2
|
+
|
|
3
|
+
@layer mw.components {
|
|
4
|
+
:root {
|
|
5
|
+
--mw-action-bar-height: 3.75rem;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Reserved while the bar is up, so focus never lands under it (WCAG 2.4.11)
|
|
9
|
+
:root:has(.mw-action-bar:not(.mw-action-bar-embedded)) {
|
|
10
|
+
--mw-action-bar-reserve: calc(
|
|
11
|
+
var(--mw-action-bar-height) + env(safe-area-inset-bottom, 0px)
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
scroll-padding-bottom: var(--mw-action-bar-reserve);
|
|
15
|
+
|
|
16
|
+
> body {
|
|
17
|
+
padding-bottom: var(--mw-action-bar-reserve);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Chrome like the header, so it takes the header's colours in both themes
|
|
22
|
+
.mw-action-bar {
|
|
23
|
+
--mw-focus-ring-color: var(--mw-header-navbar-list-active-color);
|
|
24
|
+
|
|
25
|
+
position: fixed;
|
|
26
|
+
inset: auto 0 0;
|
|
27
|
+
z-index: z-index('action-bar');
|
|
28
|
+
display: grid;
|
|
29
|
+
grid-auto-flow: column;
|
|
30
|
+
grid-auto-columns: minmax(0, 1fr);
|
|
31
|
+
align-items: stretch;
|
|
32
|
+
gap: spacing('2');
|
|
33
|
+
min-height: calc(
|
|
34
|
+
var(--mw-action-bar-height) + env(safe-area-inset-bottom, 0px)
|
|
35
|
+
);
|
|
36
|
+
padding: spacing('2') max(#{spacing('3')}, env(safe-area-inset-right, 0px))
|
|
37
|
+
calc(#{spacing('2')} + env(safe-area-inset-bottom, 0px))
|
|
38
|
+
max(#{spacing('3')}, env(safe-area-inset-left, 0px));
|
|
39
|
+
background: var(--mw-header-background);
|
|
40
|
+
border-top: 1px solid var(--mw-header-border);
|
|
41
|
+
box-shadow: 0 -6px 18px var(--mw-shadow-far);
|
|
42
|
+
|
|
43
|
+
&-embedded {
|
|
44
|
+
position: absolute;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&-item {
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
gap: spacing('1');
|
|
53
|
+
min-width: 0;
|
|
54
|
+
min-height: 2.75rem;
|
|
55
|
+
padding: spacing('1') spacing('2');
|
|
56
|
+
border: 0;
|
|
57
|
+
border-radius: radius('md');
|
|
58
|
+
background: transparent;
|
|
59
|
+
color: var(--mw-header-navbar-list-color);
|
|
60
|
+
font: inherit;
|
|
61
|
+
font-size: font-size('xs');
|
|
62
|
+
font-weight: font-weight('medium');
|
|
63
|
+
line-height: 1.15;
|
|
64
|
+
text-align: center;
|
|
65
|
+
text-decoration: none;
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
transition: var(--mw-transition-fast);
|
|
68
|
+
|
|
69
|
+
@include tappable;
|
|
70
|
+
@include focus-ring;
|
|
71
|
+
|
|
72
|
+
> i {
|
|
73
|
+
font-size: font-size('lg');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
> :is(svg, img) {
|
|
77
|
+
flex-shrink: 0;
|
|
78
|
+
width: 1.35rem;
|
|
79
|
+
height: 1.35rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
> span {
|
|
83
|
+
max-width: 100%;
|
|
84
|
+
@include truncate;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&:hover {
|
|
88
|
+
color: var(--mw-header-text-color);
|
|
89
|
+
background: color-mix(
|
|
90
|
+
in srgb,
|
|
91
|
+
var(--mw-header-text-color) 10%,
|
|
92
|
+
transparent
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@include motion-safe {
|
|
97
|
+
&:active {
|
|
98
|
+
transform: scale(0.96);
|
|
99
|
+
transition-duration: var(--mw-duration-instant);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&-primary {
|
|
105
|
+
background: var(--mw-primary-color);
|
|
106
|
+
color: var(--mw-primary-accent-text-color);
|
|
107
|
+
box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 15%, transparent);
|
|
108
|
+
|
|
109
|
+
&:hover {
|
|
110
|
+
background: var(--mw-primary-color-hover);
|
|
111
|
+
color: var(--mw-primary-accent-text-color);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@include media-up('md') {
|
|
117
|
+
:root:has(
|
|
118
|
+
.mw-action-bar:not(.mw-action-bar-embedded, .mw-action-bar-always)
|
|
119
|
+
) {
|
|
120
|
+
--mw-action-bar-reserve: 0px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.mw-action-bar:not(.mw-action-bar-always, .mw-action-bar-embedded) {
|
|
124
|
+
display: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Stretched across a desktop the four targets would sit a screen apart
|
|
128
|
+
.mw-action-bar {
|
|
129
|
+
justify-content: center;
|
|
130
|
+
grid-auto-columns: minmax(0, 10rem);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@media print {
|
|
135
|
+
:root:has(.mw-action-bar:not(.mw-action-bar-embedded)) {
|
|
136
|
+
--mw-action-bar-reserve: 0px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.mw-action-bar {
|
|
140
|
+
display: none;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
margin: 0;
|
|
39
39
|
line-height: 1.5;
|
|
40
40
|
font-size: font-size('sm');
|
|
41
|
-
opacity: 0.9;
|
|
42
41
|
|
|
43
42
|
& + p {
|
|
44
43
|
margin-top: spacing('2');
|
|
@@ -87,4 +86,17 @@
|
|
|
87
86
|
}
|
|
88
87
|
}
|
|
89
88
|
}
|
|
89
|
+
|
|
90
|
+
// Undo, Retry, a link to the details - under the message, never beside it
|
|
91
|
+
.mw-alert-actions {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-wrap: wrap;
|
|
94
|
+
gap: spacing('2');
|
|
95
|
+
margin-top: spacing('3');
|
|
96
|
+
|
|
97
|
+
// On a status tint the brand ink can fail; the alert's own text never does
|
|
98
|
+
:is(.mw-btn-link, .mw-btn-ghost) {
|
|
99
|
+
color: inherit;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
90
102
|
}
|
|
@@ -272,4 +272,21 @@
|
|
|
272
272
|
background: #{$col};
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
+
|
|
276
|
+
// The rest of a group as a count - "+4" after the faces that fit
|
|
277
|
+
.mw-avatar-more {
|
|
278
|
+
align-items: center;
|
|
279
|
+
justify-content: center;
|
|
280
|
+
background: var(--mw-surface-muted);
|
|
281
|
+
color: var(--mw-text-color);
|
|
282
|
+
font-weight: font-weight('bold');
|
|
283
|
+
font-variant-numeric: tabular-nums;
|
|
284
|
+
line-height: 1;
|
|
285
|
+
user-select: none;
|
|
286
|
+
|
|
287
|
+
// No photo, so neither the corner arc nor the sweep has anything to mark
|
|
288
|
+
&::before {
|
|
289
|
+
content: none;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
275
292
|
}
|
|
@@ -153,4 +153,16 @@
|
|
|
153
153
|
.mw-badge-status-muted .mw-badge-dot {
|
|
154
154
|
background: var(--mw-gray-color);
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
// Forced colours drop every fill: a border keeps the badge, the dot its ink
|
|
158
|
+
@media (forced-colors: active) {
|
|
159
|
+
.mw-badge {
|
|
160
|
+
border: 1px solid CanvasText;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.mw-badge-dot {
|
|
164
|
+
forced-color-adjust: none;
|
|
165
|
+
background: CanvasText;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
156
168
|
}
|