maverick-wave 4.28.0 → 5.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/.claude/settings.local.json +29 -1
- package/.claude/skills/mw-maverick-wave/SKILL.md +39 -24
- package/.claude/skills/mw-maverick-wave/examples/angular-services.md +16 -4
- package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +13 -4
- package/.claude/skills/mw-maverick-wave/references/components.md +42 -5
- package/.claude/skills/mw-maverick-wave/references/forms.md +14 -2
- package/.claude/skills/mw-maverick-wave/references/javascript.md +17 -4
- package/.claude/skills/mw-maverick-wave/references/layout.md +53 -19
- package/.claude/skills/mw-maverick-wave/references/theming.md +38 -1
- package/.impeccable/config.local.json +5 -0
- package/.impeccable/hook.cache.json +1 -0
- package/CHANGELOG.md +11 -0
- package/CLAUDE.md +5 -5
- package/README.md +48 -4
- package/index.html +19 -38
- package/maverick-wave.min.css +14 -12
- package/maverick-wave.min.js +1 -1
- package/package.json +2 -2
- package/scripts/verify.js +27 -2
- package/src/js/main.js +223 -83
- package/src/partials/accordions-container.html +6 -10
- package/src/partials/alerts-container.html +6 -6
- package/src/partials/announcement-container.html +5 -5
- package/src/partials/avatars-container.html +85 -17
- package/src/partials/badges-container.html +6 -6
- package/src/partials/blog-posts-container.html +11 -12
- package/src/partials/buttons-container.html +3 -3
- package/src/partials/cards-container.html +26 -9
- package/src/partials/code-container.html +5 -5
- package/src/partials/content-slider-container.html +5 -4
- package/src/partials/divider-container.html +7 -7
- package/src/partials/dropdown-container.html +2 -2
- package/src/partials/empty-state-container.html +5 -5
- package/src/partials/footer-container.html +21 -18
- package/src/partials/form-elements-container.html +14 -14
- package/src/partials/gallery-container.html +16 -8
- package/src/partials/get-started-container.html +4 -8
- package/src/partials/header-container.html +18 -7
- package/src/partials/home-container.html +10 -20
- package/src/partials/input-group-container.html +11 -2
- package/src/partials/kbd-container.html +1 -1
- package/src/partials/login-container.html +5 -1
- package/src/partials/media-container.html +2 -2
- package/src/partials/modals-container.html +22 -32
- package/src/partials/pricing-container.html +9 -9
- package/src/partials/skeleton-container.html +6 -6
- package/src/partials/stepper-container.html +2 -2
- package/src/partials/tables-container.html +12 -12
- package/src/partials/tabs-container.html +17 -27
- package/src/partials/tags-container.html +23 -17
- package/src/partials/techstack-bucket-container.html +13 -0
- package/src/partials/tiles-container.html +26 -9
- package/src/partials/typography-container.html +7 -6
- package/src/partials/utilities-container.html +35 -15
- package/src/scss/_layers.scss +10 -0
- package/src/scss/abstracts/_index.scss +6 -0
- package/src/scss/abstracts/_mixins.scss +61 -153
- package/src/scss/abstracts/_variables.scss +123 -319
- package/src/scss/base/_base.scss +170 -190
- package/src/scss/base/_reset.scss +106 -104
- package/src/scss/base/_typography.scss +153 -151
- package/src/scss/components/_accordions.scss +97 -97
- package/src/scss/components/_alerts.scss +71 -70
- package/src/scss/components/_announcement.scss +71 -70
- package/src/scss/components/_avatars.scss +130 -142
- package/src/scss/components/_badge.scss +131 -132
- package/src/scss/components/_blog-post.scss +223 -220
- package/src/scss/components/_breadcrumbs.scss +93 -92
- package/src/scss/components/_button-bar.scss +102 -110
- package/src/scss/components/_buttons.scss +319 -324
- package/src/scss/components/_calendar.scss +251 -252
- package/src/scss/components/_cards.scss +359 -386
- package/src/scss/components/_code.scss +190 -194
- package/src/scss/components/_coming-soon.scss +77 -75
- package/src/scss/components/_content-slider.scss +90 -89
- package/src/scss/components/_divider.scss +55 -53
- package/src/scss/components/_dropdown.scss +179 -185
- package/src/scss/components/_empty-state.scss +57 -57
- package/src/scss/components/_flag.scss +294 -278
- package/src/scss/components/_gallery.scss +131 -133
- package/src/scss/components/_info.scss +151 -167
- package/src/scss/components/_kanban.scss +332 -341
- package/src/scss/components/_kbd.scss +40 -38
- package/src/scss/components/_lang-switch.scss +89 -97
- package/src/scss/components/_links.scss +21 -28
- package/src/scss/components/_lists.scss +510 -514
- package/src/scss/components/_localhost-indicator.scss +26 -24
- package/src/scss/components/_media.scss +22 -20
- package/src/scss/components/_meta-info.scss +35 -33
- package/src/scss/components/_modals.scss +277 -186
- package/src/scss/components/_pagination.scss +81 -87
- package/src/scss/components/_panels.scss +99 -97
- package/src/scss/components/_pricing.scss +183 -241
- package/src/scss/components/_progress.scss +112 -89
- package/src/scss/components/_prose.scss +35 -33
- package/src/scss/components/_ratings.scss +40 -38
- package/src/scss/components/_segmented.scss +82 -84
- package/src/scss/components/_skeleton.scss +66 -72
- package/src/scss/components/_spinners.scss +155 -159
- package/src/scss/components/_stepper.scss +116 -116
- package/src/scss/components/_tables.scss +155 -148
- package/src/scss/components/_tabs.scss +232 -141
- package/src/scss/components/_tags.scss +109 -107
- package/src/scss/components/_techstack-bucket.scss +123 -122
- package/src/scss/components/_testimonial.scss +72 -70
- package/src/scss/components/_theme-toggle.scss +53 -51
- package/src/scss/components/_tiles.scss +174 -174
- package/src/scss/components/_timelines.scss +282 -280
- package/src/scss/components/_toasts.scss +66 -72
- package/src/scss/form-elements/_checkbox.scss +117 -132
- package/src/scss/form-elements/_form.scss +149 -115
- package/src/scss/form-elements/_input-group.scss +99 -103
- package/src/scss/form-elements/_input.scss +74 -74
- package/src/scss/form-elements/_login.scss +48 -48
- package/src/scss/form-elements/_prefilled.scss +53 -51
- package/src/scss/form-elements/_radio.scss +95 -107
- package/src/scss/form-elements/_select.scss +42 -42
- package/src/scss/form-elements/_slider.scss +117 -132
- package/src/scss/form-elements/_textarea.scss +68 -54
- package/src/scss/form-elements/_toggle.scss +127 -140
- package/src/scss/layout/_footer.scss +172 -171
- package/src/scss/layout/_grid.scss +268 -302
- package/src/scss/layout/_header.scss +426 -427
- package/src/scss/layout/_home.scss +28 -27
- package/src/scss/layout/_main.scss +275 -238
- package/src/scss/layout/_page-header.scss +38 -36
- package/src/scss/layout/_section.scss +150 -124
- package/src/scss/main.scss +1 -1
- package/src/scss/utilities/_accessibility.scss +46 -45
- package/src/scss/utilities/_aspect.scss +22 -20
- package/src/scss/utilities/_corner.scss +23 -5
- package/src/scss/utilities/_display.scss +76 -70
- package/src/scss/utilities/_elevation.scss +13 -11
- package/src/scss/utilities/_flex.scss +83 -85
- package/src/scss/utilities/_reveal.scss +40 -63
- package/src/scss/utilities/_spacing.scss +63 -64
- package/src/scss/utilities/_text.scss +139 -141
- package/src/scss/utilities/_touch-targets.scss +130 -147
|
@@ -267,39 +267,39 @@
|
|
|
267
267
|
</p>
|
|
268
268
|
<div class="mw-grid-2 mw-gap-6">
|
|
269
269
|
<div class="mw-card mw-card-simple">
|
|
270
|
-
<
|
|
270
|
+
<h4 class="mw-text-medium mw-mb-2"><code>mw-text-truncate</code></h4>
|
|
271
271
|
<p class="mw-text-truncate">
|
|
272
272
|
One line only: this sentence is far longer than the box it has been given
|
|
273
273
|
and ends in an ellipsis rather than wrapping.
|
|
274
274
|
</p>
|
|
275
|
-
<
|
|
275
|
+
<h4 class="mw-text-medium mw-mb-2 mw-mt-5">
|
|
276
276
|
<code>mw-text-clamp-2</code>
|
|
277
|
-
</
|
|
277
|
+
</h4>
|
|
278
278
|
<p class="mw-text-clamp-2">
|
|
279
279
|
Two lines and then an ellipsis. This paragraph runs on for long enough
|
|
280
280
|
that the third line is cut off, which is what a card preview or a list
|
|
281
281
|
subtitle wants when the copy is not yours to control.
|
|
282
282
|
</p>
|
|
283
|
-
<
|
|
283
|
+
<h4 class="mw-text-medium mw-mb-2 mw-mt-5">
|
|
284
284
|
<code>mw-text-break</code>
|
|
285
|
-
</
|
|
285
|
+
</h4>
|
|
286
286
|
<p class="mw-text-break">
|
|
287
287
|
https://example.com/a/very/long/url/that/has/no/spaces/in/it/at/all/and/would/otherwise/push/the/page/sideways
|
|
288
288
|
</p>
|
|
289
289
|
</div>
|
|
290
290
|
<div class="mw-card mw-card-simple">
|
|
291
|
-
<
|
|
291
|
+
<h4 class="mw-text-medium mw-mb-2">
|
|
292
292
|
<code>mw-text-balance</code> and <code>mw-text-pretty</code>
|
|
293
|
-
</
|
|
293
|
+
</h4>
|
|
294
294
|
<p class="mw-text-muted mw-text-sm">
|
|
295
295
|
Headings get <code>balance</code> by default - it evens the lines out so
|
|
296
296
|
no headline leaves one word alone on the last one. Paragraphs get
|
|
297
297
|
<code>pretty</code>, which only prevents the orphan. Both are on already;
|
|
298
298
|
the classes are for anything the framework does not style itself.
|
|
299
299
|
</p>
|
|
300
|
-
<
|
|
300
|
+
<h4 class="mw-text-medium mw-mb-2 mw-mt-5">
|
|
301
301
|
<code>mw-text-eyebrow</code>
|
|
302
|
-
</
|
|
302
|
+
</h4>
|
|
303
303
|
<p class="mw-text-eyebrow mw-mb-1">Release notes</p>
|
|
304
304
|
<h4 class="mw-mb-0">The kicker above a heading</h4>
|
|
305
305
|
<h5 class="mw-text-medium mw-mb-2 mw-mt-5">
|
|
@@ -323,29 +323,29 @@
|
|
|
323
323
|
</p>
|
|
324
324
|
<div class="mw-grid-3 mw-gap-6">
|
|
325
325
|
<div class="mw-card mw-card-simple mw-elevation-1">
|
|
326
|
-
<
|
|
326
|
+
<h4 class="mw-text-medium mw-mb-1">1 · resting</h4>
|
|
327
327
|
<p class="mw-text-muted mw-text-sm mw-mb-0">
|
|
328
328
|
Inputs, tags, small controls.
|
|
329
329
|
</p>
|
|
330
330
|
</div>
|
|
331
331
|
<div class="mw-card mw-card-simple mw-elevation-2">
|
|
332
|
-
<
|
|
332
|
+
<h4 class="mw-text-medium mw-mb-1">2 · raised</h4>
|
|
333
333
|
<p class="mw-text-muted mw-text-sm mw-mb-0">Cards and panels at rest.</p>
|
|
334
334
|
</div>
|
|
335
335
|
<div class="mw-card mw-card-simple mw-elevation-3">
|
|
336
|
-
<
|
|
336
|
+
<h4 class="mw-text-medium mw-mb-1">3 · floating</h4>
|
|
337
337
|
<p class="mw-text-muted mw-text-sm mw-mb-0">A card under the pointer.</p>
|
|
338
338
|
</div>
|
|
339
339
|
<div class="mw-card mw-card-simple mw-elevation-4">
|
|
340
|
-
<
|
|
340
|
+
<h4 class="mw-text-medium mw-mb-1">4 · overlay</h4>
|
|
341
341
|
<p class="mw-text-muted mw-text-sm mw-mb-0">Dropdowns, popovers, drawer.</p>
|
|
342
342
|
</div>
|
|
343
343
|
<div class="mw-card mw-card-simple mw-elevation-5">
|
|
344
|
-
<
|
|
344
|
+
<h4 class="mw-text-medium mw-mb-1">5 · modal</h4>
|
|
345
345
|
<p class="mw-text-muted mw-text-sm mw-mb-0">The dialog over everything.</p>
|
|
346
346
|
</div>
|
|
347
347
|
<div class="mw-card mw-card-simple mw-elevation-0">
|
|
348
|
-
<
|
|
348
|
+
<h4 class="mw-text-medium mw-mb-1">0 · flat</h4>
|
|
349
349
|
<p class="mw-text-muted mw-text-sm mw-mb-0">Explicitly on the page.</p>
|
|
350
350
|
</div>
|
|
351
351
|
</div>
|
|
@@ -403,3 +403,23 @@
|
|
|
403
403
|
<code>photo</code>
|
|
404
404
|
</div>
|
|
405
405
|
</div>
|
|
406
|
+
|
|
407
|
+
<h3 class="mw-mb-4 mw-mt-6">Squircle Corners</h3>
|
|
408
|
+
<p class="mw-text-muted mw-text-measure">
|
|
409
|
+
<code>mw-squircle</code> draws the framework silhouette with a superellipse
|
|
410
|
+
instead of a circular arc - same four radii, fuller curve. Opt-in, because
|
|
411
|
+
<code>corner-shape</code> only lands in Chromium so far; everywhere else the
|
|
412
|
+
card below is simply the normal one.
|
|
413
|
+
</p>
|
|
414
|
+
<div class="mw-grid-2 mw-gap-6">
|
|
415
|
+
<div class="mw-card mw-card-simple">
|
|
416
|
+
<strong>Default</strong>
|
|
417
|
+
<p class="mw-text-muted mw-text-sm mw-mb-0">Circular corner radii.</p>
|
|
418
|
+
</div>
|
|
419
|
+
<div class="mw-card mw-card-simple mw-squircle">
|
|
420
|
+
<strong>mw-squircle</strong>
|
|
421
|
+
<p class="mw-text-muted mw-text-sm mw-mb-0">
|
|
422
|
+
Superellipse, corner accent follows.
|
|
423
|
+
</p>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Declared here and before any rule: a layer's position is fixed by where its
|
|
2
|
+
// name first appears. What it buys a consumer is that any rule outside a layer
|
|
3
|
+
// beats every rule inside one, however specific.
|
|
4
|
+
//
|
|
5
|
+
// The order reads inside out - the smaller thing first, then whatever places it.
|
|
6
|
+
// Two steps are worth stating: forms before components, because a list restyles
|
|
7
|
+
// the checkbox inside it; components before layout, because the two meet on one
|
|
8
|
+
// element (`class="mw-card mw-grid-2"`) and there the layout class has to win, or
|
|
9
|
+
// `.mw-card` hands `display: block` back to a grid.
|
|
10
|
+
@layer mw.reset, mw.base, mw.forms, mw.components, mw.layout, mw.utilities;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// Here and not only in main.scss: every partial loads `abstracts`, so this is the
|
|
2
|
+
// one point every entry reaches. Importing components one by one otherwise
|
|
3
|
+
// leaves the layer order to the import order, which puts `layout` ahead of
|
|
4
|
+
// `components` and hands `display: block` back to a card that is also a grid.
|
|
5
|
+
@use '../layers';
|
|
6
|
+
|
|
1
7
|
// 'variables' first: it is the only configurable module, and both 'functions'
|
|
2
8
|
// and 'mixins' load it themselves. Forwarding it later would mean it is
|
|
3
9
|
// already loaded by the time a `with (...)` configuration reaches it.
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
@use 'variables' as v;
|
|
3
3
|
@use 'functions' as *;
|
|
4
4
|
|
|
5
|
-
//
|
|
5
|
+
// `media-down` stops 0.02px short, or both ranges match at exactly 768px - an
|
|
6
|
+
// iPad in portrait, where mw-hide-mobile and mw-hide-desktop would both hide.
|
|
7
|
+
// 0.02 and not 1, because a viewport can be fractional (zoom, scaled display).
|
|
6
8
|
@mixin media-up($breakpoint) {
|
|
7
9
|
@media (min-width: map.get(v.$breakpoints, $breakpoint)) {
|
|
8
10
|
@content;
|
|
@@ -10,51 +12,15 @@
|
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
@mixin media-down($breakpoint) {
|
|
13
|
-
@media (max-width: map.get(v.$breakpoints, $breakpoint)) {
|
|
15
|
+
@media (max-width: map.get(v.$breakpoints, $breakpoint) - 0.02px) {
|
|
14
16
|
@content;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
$align: stretch,
|
|
23
|
-
$wrap: nowrap
|
|
24
|
-
) {
|
|
25
|
-
display: flex;
|
|
26
|
-
flex-direction: $direction;
|
|
27
|
-
justify-content: $justify;
|
|
28
|
-
align-items: $align;
|
|
29
|
-
flex-wrap: $wrap;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Grid mixins
|
|
33
|
-
@mixin grid($columns: 1, $gap: 1rem) {
|
|
34
|
-
display: grid;
|
|
35
|
-
grid-template-columns: repeat($columns, 1fr);
|
|
36
|
-
gap: $gap;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@mixin media-between($min, $max) {
|
|
40
|
-
$min-width: map.get(v.$breakpoints, $min);
|
|
41
|
-
$max-width: map.get(v.$breakpoints, $max) - 1px;
|
|
42
|
-
|
|
43
|
-
@media (min-width: $min-width) and (max-width: $max-width) {
|
|
44
|
-
@content;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Scroll hint for a horizontally scrollable strip - a tab bar, a wide table.
|
|
49
|
-
//
|
|
50
|
-
// Four gradient layers in two pairs. The cover pair is attached to the content
|
|
51
|
-
// (`local`) and therefore scrolls out of the way once that edge is reached;
|
|
52
|
-
// the shadow pair stays on the frame (`scroll`). Net effect: a shadow shows
|
|
53
|
-
// only on the side that still has something hidden behind it. No JavaScript,
|
|
54
|
-
// no scroll listener.
|
|
55
|
-
//
|
|
56
|
-
// The cover has to match whatever the strip sits on, which is why it reads a
|
|
57
|
-
// token: preset to the page, re-pointed inside cards, panels and modals.
|
|
20
|
+
// Four gradients in two pairs: the cover pair is attached to the content and
|
|
21
|
+
// scrolls out of the way at the edge, the shadow pair stays on the frame - so a
|
|
22
|
+
// shadow shows only where something is still hidden. No scroll listener.
|
|
23
|
+
// The cover reads a token because it has to match whatever the strip sits on.
|
|
58
24
|
@mixin scroll-hint {
|
|
59
25
|
background-image:
|
|
60
26
|
linear-gradient(
|
|
@@ -79,17 +45,8 @@
|
|
|
79
45
|
background-attachment: local, local, scroll, scroll;
|
|
80
46
|
}
|
|
81
47
|
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
// The ring was written out by hand in nine places before this, in two different
|
|
86
|
-
// shapes, and a form field had a third. One mixin per shape instead, so the
|
|
87
|
-
// whole framework moves when the ring is retuned.
|
|
88
|
-
//
|
|
89
|
-
// `:focus-visible` and never `:focus`: a mouse click on a button should not
|
|
90
|
-
// leave it ringed. The browser decides what counts - a keyboard tab does, a
|
|
91
|
-
// pointer press on a button does not, a pointer press into a text field does.
|
|
92
|
-
// ---------------------------------------------------------------------------
|
|
48
|
+
// `:focus-visible` and never `:focus`: a mouse click on a button should not leave
|
|
49
|
+
// it ringed, and the browser is the one that knows which press counts.
|
|
93
50
|
@mixin focus-ring(
|
|
94
51
|
$offset: var(--mw-focus-ring-offset),
|
|
95
52
|
$color: var(--mw-focus-ring-color)
|
|
@@ -101,9 +58,7 @@
|
|
|
101
58
|
}
|
|
102
59
|
}
|
|
103
60
|
|
|
104
|
-
// Same ring,
|
|
105
|
-
// a segment inside a segmented control, a cell inside a table - where a ring on
|
|
106
|
-
// the outside would be cut off by the parent.
|
|
61
|
+
// Same ring, inside the element - for anything its parent would clip
|
|
107
62
|
@mixin focus-ring-inset($inset: -2px) {
|
|
108
63
|
&:focus-visible {
|
|
109
64
|
outline: var(--mw-focus-ring-width) solid var(--mw-focus-ring-color);
|
|
@@ -112,18 +67,10 @@
|
|
|
112
67
|
}
|
|
113
68
|
}
|
|
114
69
|
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
// The border is drawn *on* the field, which is light in both themes, so it takes
|
|
120
|
-
// the fill tone. The halo spreads *outside* it, onto the page or the card, so it
|
|
121
|
-
// takes the ink tone - the theme-aware one. Using the fill tone for both is what
|
|
122
|
-
// made the dark theme's halo a dark blue haze on a dark blue page.
|
|
123
|
-
//
|
|
124
|
-
// `outline: none` is only safe because the halo *is* the indicator - except in
|
|
125
|
-
// forced-colors mode, where box-shadow is dropped and the field would be left
|
|
126
|
-
// with nothing. The guard hands the outline back there.
|
|
70
|
+
// Two tones on purpose: the border is drawn *on* the field, which is light in
|
|
71
|
+
// both themes, so it takes the fill tone; the halo spreads onto the page and
|
|
72
|
+
// takes the theme-aware ink tone. `outline: none` is safe because the halo is the
|
|
73
|
+
// indicator - except under forced-colors, where the guard hands it back.
|
|
127
74
|
@mixin field-focus(
|
|
128
75
|
$trigger: 'focus',
|
|
129
76
|
$border: 'primary-color',
|
|
@@ -144,8 +91,7 @@
|
|
|
144
91
|
}
|
|
145
92
|
}
|
|
146
93
|
|
|
147
|
-
//
|
|
148
|
-
// radio, a switch track, a calendar day - and only want the ring around it.
|
|
94
|
+
// For controls that draw their own box and only want the ring around it
|
|
149
95
|
@mixin focus-halo($color: 'primary-text-color') {
|
|
150
96
|
box-shadow: 0 0 0 var(--mw-focus-halo-size)
|
|
151
97
|
color-mix(
|
|
@@ -155,15 +101,26 @@
|
|
|
155
101
|
);
|
|
156
102
|
}
|
|
157
103
|
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
//
|
|
104
|
+
// Both spellings: `mw-active` is documented, plain `active` is what older markup
|
|
105
|
+
// carries, and a state toggled off in one must not stay lit in the other.
|
|
106
|
+
// $suffix qualifies the state, e.g. `@include active(':not(:disabled)')`.
|
|
107
|
+
@mixin active($suffix: '') {
|
|
108
|
+
&.mw-active#{$suffix},
|
|
109
|
+
&.active#{$suffix} {
|
|
110
|
+
@content;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Without the `min-width: 0` that mw-text-truncate carries: that fixes the layout
|
|
115
|
+
// around the text, and handing it to seven components would change how they size
|
|
116
|
+
@mixin truncate {
|
|
117
|
+
white-space: nowrap;
|
|
118
|
+
overflow: hidden;
|
|
119
|
+
text-overflow: ellipsis;
|
|
120
|
+
}
|
|
161
121
|
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
// and stays on until you tap somewhere else, so a lifted card stays lifted and
|
|
165
|
-
// a grid of them ends up with one member permanently out of line. Colour
|
|
166
|
-
// changes are fine unguarded; movement is not.
|
|
122
|
+
// For hover effects that *move* something. On touch `:hover` latches after a tap,
|
|
123
|
+
// so a lifted card stays lifted. Colour changes are fine unguarded, movement is not.
|
|
167
124
|
@mixin hover {
|
|
168
125
|
@media (hover: hover) and (pointer: fine) {
|
|
169
126
|
&:hover {
|
|
@@ -172,25 +129,16 @@
|
|
|
172
129
|
}
|
|
173
130
|
}
|
|
174
131
|
|
|
175
|
-
//
|
|
176
|
-
// double-tap that is never coming, and no grey box flashing over it while the
|
|
177
|
-
// press is held - the component draws its own :active state instead.
|
|
132
|
+
// No 300ms double-tap wait, no grey flash - the component draws its own :active
|
|
178
133
|
@mixin tappable {
|
|
179
134
|
touch-action: manipulation;
|
|
180
135
|
-webkit-tap-highlight-color: transparent;
|
|
181
136
|
}
|
|
182
137
|
|
|
183
|
-
//
|
|
184
|
-
// Scrollbar
|
|
185
|
-
//
|
|
186
|
-
// Was written per list variant, which is why three of them had a thumb the same
|
|
187
|
-
// colour as their track. One shape, used by every scroll container and by the
|
|
188
|
-
// page itself.
|
|
189
|
-
// ---------------------------------------------------------------------------
|
|
138
|
+
// One shape for every scroll container and the page itself
|
|
190
139
|
@mixin scrollbar($thumb: var(--mw-text-muted-color), $track: transparent) {
|
|
191
140
|
scrollbar-width: thin;
|
|
192
|
-
// Firefox
|
|
193
|
-
// whole thing is dropped, which is how a thumb ends up invisible.
|
|
141
|
+
// Firefox needs both values - a single one is invalid and drops the declaration
|
|
194
142
|
scrollbar-color: #{$thumb} #{$track};
|
|
195
143
|
|
|
196
144
|
&::-webkit-scrollbar {
|
|
@@ -217,28 +165,16 @@
|
|
|
217
165
|
}
|
|
218
166
|
}
|
|
219
167
|
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
// Two things, and both are what separates a button from a coloured rectangle: a
|
|
224
|
-
// hairline of light along the top edge, as if there were a light source above
|
|
225
|
-
// the page, and a shadow underneath that says the button sits on the surface
|
|
226
|
-
// rather than in it. The pressed state inverts both - the highlight goes and an
|
|
227
|
-
// inner shadow takes its place, which is the whole of what "pushed in" looks
|
|
228
|
-
// like.
|
|
229
|
-
//
|
|
230
|
-
// White and black rather than tokens on purpose: this is lighting, not palette.
|
|
231
|
-
// It has to behave the same on a primary, a danger and whatever a project
|
|
232
|
-
// overrides them with.
|
|
168
|
+
// A hairline of light along the top edge and a shadow underneath, as if the light
|
|
169
|
+
// came from above the page; the pressed state inverts both. White and black and
|
|
170
|
+
// not tokens on purpose - this is lighting, not palette.
|
|
233
171
|
@mixin btn-solid {
|
|
234
172
|
box-shadow:
|
|
235
173
|
inset 0 1px 0 color-mix(in srgb, #fff 15%, transparent),
|
|
236
174
|
var(--mw-elevation-1);
|
|
237
175
|
|
|
238
|
-
// A pixel up
|
|
239
|
-
//
|
|
240
|
-
// as clearly, and the lift is small enough that a row of buttons does not
|
|
241
|
-
// twitch. Guarded, so it never latches after a tap.
|
|
176
|
+
// A pixel up and the shadow steps with it - the pair reads as the button coming
|
|
177
|
+
// toward the pointer. Guarded, so it never latches after a tap.
|
|
242
178
|
@include hover {
|
|
243
179
|
box-shadow:
|
|
244
180
|
inset 0 1px 0 color-mix(in srgb, #fff 20%, transparent),
|
|
@@ -255,11 +191,8 @@
|
|
|
255
191
|
}
|
|
256
192
|
}
|
|
257
193
|
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
// it. Shared by `mw-link` in running text and `mw-btn-link` in a row of
|
|
261
|
-
// buttons - the two differ in whether they carry a control height, not in how
|
|
262
|
-
// they look.
|
|
194
|
+
// Shared by mw-link and mw-btn-link, which differ in whether they carry a control
|
|
195
|
+
// height, not in how they look. The underline sits low so descenders clear it.
|
|
263
196
|
@mixin link-look {
|
|
264
197
|
background: transparent;
|
|
265
198
|
border: none;
|
|
@@ -272,27 +205,13 @@
|
|
|
272
205
|
}
|
|
273
206
|
}
|
|
274
207
|
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
// The MaverickWave silhouette: sharp corners on the top-left/bottom-right
|
|
279
|
-
// diagonal, round ones on the other. Nine components repeated those four radii
|
|
280
|
-
// by hand - this is the only place the shape is defined now.
|
|
281
|
-
//
|
|
282
|
-
// On top of the radii, an accent arc on the two round corners. The asymmetry
|
|
283
|
-
// alone reads as an accident; a coloured bow sitting exactly on it does not.
|
|
284
|
-
// Point-symmetric like the radii themselves, so it holds up on a tall card, a
|
|
285
|
-
// wide panel and a square tile alike.
|
|
286
|
-
//
|
|
287
|
-
// The ring is drawn inside the padding box rather than on the border, because
|
|
288
|
-
// four of the callers clip with `overflow: hidden` and would swallow a ring
|
|
289
|
-
// sitting on the border edge. Hence $border-width: `inset: 0` already lands on
|
|
290
|
-
// the padding box, but the corner radius there is the outer one minus the
|
|
291
|
-
// border, and a ring drawn at the outer radius would visibly miss the curve.
|
|
208
|
+
// The MaverickWave silhouette: sharp corners on one diagonal, round on the other,
|
|
209
|
+
// with an accent arc on the round pair - the asymmetry alone reads as an accident.
|
|
292
210
|
//
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
//
|
|
211
|
+
// The ring is drawn inside the padding box, because four callers clip with
|
|
212
|
+
// `overflow: hidden`. Hence $border-width: the radius there is the outer one minus
|
|
213
|
+
// the border, and a ring at the outer radius would miss the curve. $corners drops
|
|
214
|
+
// the top arc where a fill already owns that corner.
|
|
296
215
|
@mixin surface($border-width: 1px, $corners: 'both') {
|
|
297
216
|
position: relative;
|
|
298
217
|
border-radius: radius('sm') radius('xl') radius('sm') radius('xl');
|
|
@@ -302,20 +221,14 @@
|
|
|
302
221
|
}
|
|
303
222
|
}
|
|
304
223
|
|
|
305
|
-
// The arc
|
|
306
|
-
// shape - it is already on the element by then.
|
|
224
|
+
// The arc alone, for a variant that redraws it without restating the shape
|
|
307
225
|
@mixin corner-accent($border-width: 1px, $corners: 'both') {
|
|
308
226
|
$sharp: radius('sm') - $border-width;
|
|
309
227
|
$round: radius('xl') - $border-width;
|
|
310
|
-
// Opaque
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
// shortest surface rather than by the nicest-looking card: the fade reaches
|
|
315
|
-
// from a corner, so on a 50px-high box - `mw-card-simple` with one line in it
|
|
316
|
-
// - anything past about 2 lets the two arcs meet in the middle and the pair
|
|
317
|
-
// stops reading as two corners and starts reading as a frame. Higher is
|
|
318
|
-
// softer on a tall card, lower is more defined on a short one.
|
|
228
|
+
// Opaque to where the curve ends, fading from there, so the arc runs into the
|
|
229
|
+
// straight edge instead of stopping at the tangent. 1.8 is bounded by the
|
|
230
|
+
// shortest surface: past about 2 the two arcs meet on a 50px box and read as
|
|
231
|
+
// a frame.
|
|
319
232
|
$reach: $round * 1.8;
|
|
320
233
|
$top: radial-gradient(circle $reach at 100% 0, #000 $round, transparent 100%);
|
|
321
234
|
$bottom: radial-gradient(
|
|
@@ -328,9 +241,8 @@
|
|
|
328
241
|
position: absolute;
|
|
329
242
|
inset: 0;
|
|
330
243
|
pointer-events: none;
|
|
331
|
-
// 2px
|
|
332
|
-
//
|
|
333
|
-
// border by little more than its saturation and vanishes at reading distance.
|
|
244
|
+
// 2px, or in the dark theme the arc is separated from the plain border by little
|
|
245
|
+
// more than its saturation and vanishes at reading distance
|
|
334
246
|
border: 2px solid var(--mw-corner-accent);
|
|
335
247
|
border-radius: $sharp $round $sharp $round;
|
|
336
248
|
|
|
@@ -341,13 +253,9 @@
|
|
|
341
253
|
}
|
|
342
254
|
}
|
|
343
255
|
|
|
344
|
-
// The
|
|
345
|
-
//
|
|
346
|
-
//
|
|
347
|
-
// the screen instead of the short one snapping in. The zone starts 8dvh above
|
|
348
|
-
// the bottom edge - right at the edge nobody sees the motion - and ends at
|
|
349
|
-
// 34dvh, still in the lower third, so nothing is moving while someone already
|
|
350
|
-
// reads it. Each further column of a row starts 4dvh later than the one before.
|
|
256
|
+
// The reveal zone as the range of the n-th column. Viewport lengths and not
|
|
257
|
+
// percentages of the block, so a short band and a tall card rise through the same
|
|
258
|
+
// region of the screen. Each further column starts 4dvh after the one before.
|
|
351
259
|
@mixin reveal-range($column: 1) {
|
|
352
260
|
$shift: 4dvh * ($column - 1);
|
|
353
261
|
|