maverick-wave 5.7.0 → 5.10.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/skills/mw-maverick-wave/SKILL.md +22 -12
- package/.claude/skills/mw-maverick-wave/examples/angular-services.md +10 -1
- package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +4 -3
- package/.claude/skills/mw-maverick-wave/references/components.md +23 -9
- package/.claude/skills/mw-maverick-wave/references/javascript.md +1 -1
- package/.claude/skills/mw-maverick-wave/references/layout.md +8 -3
- package/.claude/skills/mw-maverick-wave/references/theming.md +57 -29
- package/CHANGELOG.md +19 -0
- package/README.md +43 -22
- package/index.html +395 -62
- package/maverick-wave.min.css +61 -5
- package/maverick-wave.min.js +1 -1
- package/package.json +2 -2
- package/scripts/verify.js +18 -2
- package/src/js/main.js +24 -5
- package/src/partials/header-container.html +7 -5
- package/src/partials/palette-container.html +176 -66
- package/src/partials/preview-container.html +136 -0
- package/src/partials/utilities-container.html +55 -4
- package/src/scss/abstracts/_functions.scss +31 -3
- package/src/scss/abstracts/_mixins.scss +62 -12
- package/src/scss/abstracts/_variables.scss +47 -21
- package/src/scss/base/_base.scss +101 -8
- package/src/scss/base/_reset.scss +2 -0
- package/src/scss/components/_badge.scss +1 -1
- package/src/scss/components/_buttons.scss +1 -1
- package/src/scss/components/_cards.scss +23 -14
- package/src/scss/components/_dropdown.scss +58 -1
- package/src/scss/components/_kanban.scss +10 -9
- package/src/scss/components/_lang-switch.scss +1 -1
- package/src/scss/components/_localhost-indicator.scss +1 -1
- package/src/scss/components/_modals.scss +13 -1
- package/src/scss/components/_pricing.scss +1 -1
- package/src/scss/components/_progress.scss +9 -5
- package/src/scss/components/_skeleton.scss +1 -1
- package/src/scss/components/_spinners.scss +5 -5
- package/src/scss/components/_stepper.scss +4 -1
- package/src/scss/components/_tabs.scss +28 -8
- package/src/scss/components/_tiles.scss +41 -16
- package/src/scss/components/_timelines.scss +12 -5
- package/src/scss/layout/_main.scss +1 -1
- package/src/scss/layout/_parallax.scss +10 -5
- package/src/scss/utilities/_elevation.scss +23 -0
- package/src/scss/utilities/_touch-targets.scss +1 -1
- package/src/scss/utilities/_variants.scss +115 -6
|
@@ -57,7 +57,22 @@
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// The tile sizes its type off its own width, not the window's. In
|
|
61
|
+
// `.mw-tiles-4col` on a wide desktop a tile is a quarter of 85% of the page -
|
|
62
|
+
// narrower than the same tile alone on a phone, where it used to be the one
|
|
63
|
+
// getting the small type.
|
|
64
|
+
//
|
|
65
|
+
// The cost: `container-type` makes the tile a containing block for its own
|
|
66
|
+
// fixed-position descendants, and unlike a card the tile clips - so a
|
|
67
|
+
// [data-tooltip] inside one is now cut off at its edge. Taken knowingly, there
|
|
68
|
+
// being nothing in a tile's anatomy that wants a tooltip. Drop the two lines
|
|
69
|
+
// below and the queries fall back to the window.
|
|
70
|
+
$_mw-tile-wide: 300px;
|
|
71
|
+
$_mw-tile-narrow: 220px;
|
|
72
|
+
|
|
60
73
|
.mw-tile {
|
|
74
|
+
width: 100%;
|
|
75
|
+
container: mw-tile / inline-size;
|
|
61
76
|
background: var(--mw-card-background);
|
|
62
77
|
@include surface;
|
|
63
78
|
padding: spacing('5');
|
|
@@ -116,11 +131,11 @@
|
|
|
116
131
|
line-height: 1.2;
|
|
117
132
|
text-align: center;
|
|
118
133
|
|
|
119
|
-
@
|
|
134
|
+
@container mw-tile (width >= #{$_mw-tile-narrow}) {
|
|
120
135
|
font-size: font-size('xl');
|
|
121
136
|
}
|
|
122
137
|
|
|
123
|
-
@
|
|
138
|
+
@container mw-tile (width >= #{$_mw-tile-wide}) {
|
|
124
139
|
font-size: font-size('2xl');
|
|
125
140
|
}
|
|
126
141
|
}
|
|
@@ -166,7 +181,7 @@
|
|
|
166
181
|
font-size: font-size('md');
|
|
167
182
|
margin-bottom: spacing('2');
|
|
168
183
|
|
|
169
|
-
@
|
|
184
|
+
@container mw-tile (width >= #{$_mw-tile-wide}) {
|
|
170
185
|
font-size: font-size('lg');
|
|
171
186
|
}
|
|
172
187
|
}
|
|
@@ -194,11 +209,11 @@
|
|
|
194
209
|
font-size: font-size('xl');
|
|
195
210
|
margin-bottom: spacing('4');
|
|
196
211
|
|
|
197
|
-
@
|
|
212
|
+
@container mw-tile (width >= #{$_mw-tile-narrow}) {
|
|
198
213
|
font-size: font-size('2xl');
|
|
199
214
|
}
|
|
200
215
|
|
|
201
|
-
@
|
|
216
|
+
@container mw-tile (width >= #{$_mw-tile-wide}) {
|
|
202
217
|
font-size: font-size('3xl');
|
|
203
218
|
}
|
|
204
219
|
}
|
|
@@ -214,20 +229,30 @@
|
|
|
214
229
|
}
|
|
215
230
|
}
|
|
216
231
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
232
|
+
// A cramped tile reads better ranged left whatever the window is doing - a
|
|
233
|
+
// centred line inside 200px is two words and a gap. Every selector here is a
|
|
234
|
+
// child: a container cannot answer a query about itself, and the tile *is* the
|
|
235
|
+
// container - which is also why the padding below stays on the window.
|
|
236
|
+
@container mw-tile (width < #{$_mw-tile-narrow}) {
|
|
237
|
+
.mw-tile-header,
|
|
238
|
+
.mw-tile-body {
|
|
220
239
|
text-align: left;
|
|
240
|
+
}
|
|
221
241
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
margin: spacing('0') auto spacing('2');
|
|
226
|
-
}
|
|
242
|
+
.mw-tile-body {
|
|
243
|
+
margin-bottom: spacing('2');
|
|
244
|
+
}
|
|
227
245
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
246
|
+
.mw-tile-img {
|
|
247
|
+
width: 60px;
|
|
248
|
+
height: 60px;
|
|
249
|
+
margin: spacing('0') auto spacing('2');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@include media-down('sm') {
|
|
254
|
+
.mw-tile {
|
|
255
|
+
padding: spacing('4');
|
|
231
256
|
}
|
|
232
257
|
}
|
|
233
258
|
}
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
margin: spacing('1') auto;
|
|
58
58
|
padding: spacing('5') 0;
|
|
59
59
|
width: min(100%, 900px);
|
|
60
|
+
container: mw-timeline / inline-size;
|
|
60
61
|
|
|
61
62
|
// Center vertical line
|
|
62
63
|
&::before {
|
|
@@ -185,7 +186,7 @@
|
|
|
185
186
|
background: var(--mw-primary-color);
|
|
186
187
|
border-color: var(--mw-primary-text-color);
|
|
187
188
|
transform: scale(1.1);
|
|
188
|
-
animation: mw-pulse-ring-big 2s infinite;
|
|
189
|
+
animation: mw-pulse-ring-big motion(2s) infinite;
|
|
189
190
|
|
|
190
191
|
.mw-timeline-big-date-main,
|
|
191
192
|
.mw-timeline-big-date-sub {
|
|
@@ -193,9 +194,10 @@
|
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
// The two-sided layout collapses when the timeline itself runs out of room,
|
|
198
|
+
// not when the window does - the same timeline in a half-width column had
|
|
199
|
+
// its content overlapping the centre line on a wide desktop.
|
|
200
|
+
@container mw-timeline (width < #{breakpoint('sm')}) {
|
|
199
201
|
// Line moves to the left
|
|
200
202
|
&::before {
|
|
201
203
|
left: 0;
|
|
@@ -258,6 +260,7 @@
|
|
|
258
260
|
margin: spacing('1') auto;
|
|
259
261
|
padding: spacing('3') 0;
|
|
260
262
|
width: min(96%, 930px);
|
|
263
|
+
container: mw-timeline / inline-size;
|
|
261
264
|
|
|
262
265
|
// Vertical line centered over the date column
|
|
263
266
|
&::before {
|
|
@@ -319,12 +322,16 @@
|
|
|
319
322
|
background: var(--mw-primary-color);
|
|
320
323
|
color: var(--mw-primary-accent-text-color);
|
|
321
324
|
transform: scale(1.1);
|
|
322
|
-
animation: mw-pulse-ring-simple 2s infinite;
|
|
325
|
+
animation: mw-pulse-ring-simple motion(2s) infinite;
|
|
323
326
|
}
|
|
324
327
|
|
|
328
|
+
// The inset is a page-level call: on a phone the timeline takes the full
|
|
329
|
+
// width, however wide its column happens to be.
|
|
325
330
|
@include media-down('sm') {
|
|
326
331
|
width: 100%;
|
|
332
|
+
}
|
|
327
333
|
|
|
334
|
+
@container mw-timeline (width < #{breakpoint('sm')}) {
|
|
328
335
|
&::before {
|
|
329
336
|
left: 0;
|
|
330
337
|
transform: none;
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
letter-spacing: 0.08em;
|
|
209
209
|
text-transform: uppercase;
|
|
210
210
|
text-decoration: none;
|
|
211
|
-
animation: mw-scroll-hint-float 2.2s var(--mw-ease-in-out) infinite;
|
|
211
|
+
animation: mw-scroll-hint-float motion(2.2s) var(--mw-ease-in-out) infinite;
|
|
212
212
|
text-shadow: 0 1px 4px rgb(0 0 0 / 65%);
|
|
213
213
|
|
|
214
214
|
// The arrow carries the meaning, so it gets the size and the label stays quiet
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
@use '../abstracts' as *;
|
|
2
2
|
|
|
3
3
|
@layer mw.layout {
|
|
4
|
+
// Registered so a bad value cannot invalidate the calc() and drop the layer
|
|
5
|
+
// somewhere else. 0.5 and not 0 is the resting point - see the transform
|
|
6
|
+
// at the bottom of this file.
|
|
7
|
+
@property --mw-parallax-progress {
|
|
8
|
+
syntax: '<number>';
|
|
9
|
+
inherits: true;
|
|
10
|
+
initial-value: 0.5;
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
// The image gets its own layer instead of `background-attachment: fixed`: that
|
|
5
14
|
// one is ignored on iOS and sizes against the viewport rather than the block.
|
|
6
15
|
// Here a transform runs on the browser's own scroll timeline - no listener, no
|
|
@@ -151,13 +160,9 @@
|
|
|
151
160
|
// is what lets every depth variant above - and an inline
|
|
152
161
|
// `--mw-parallax-depth` - go on working untouched.
|
|
153
162
|
//
|
|
154
|
-
// 0 puts the layer at +depth and 1 at -depth, the two ends of the keyframes
|
|
155
|
-
// below. Declared and not only used, so the frame before the script has
|
|
156
|
-
// written anything sits at rest instead of nowhere.
|
|
163
|
+
// 0 puts the layer at +depth and 1 at -depth, the two ends of the keyframes.
|
|
157
164
|
@media (prefers-reduced-motion: no-preference) {
|
|
158
165
|
.mw-parallax-driven {
|
|
159
|
-
--mw-parallax-progress: 0.5;
|
|
160
|
-
|
|
161
166
|
transform: translate3d(
|
|
162
167
|
0,
|
|
163
168
|
calc(var(--mw-parallax-depth) * (1 - 2 * var(--mw-parallax-progress))),
|
|
@@ -15,4 +15,27 @@
|
|
|
15
15
|
box-shadow: var(--mw-elevation-#{$level});
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
// Light instead of shadow. Elevation says how far a surface floats above the
|
|
20
|
+
// page; this says it is the thing giving off the light - for the one element on
|
|
21
|
+
// a screen that has to be looked at first, and for nothing else.
|
|
22
|
+
//
|
|
23
|
+
// Two layers like elevation, and for the same reason: the tight one reads as
|
|
24
|
+
// the edge of the source, the wide one as the air around it. Both are
|
|
25
|
+
// offsetless, which is what separates a glow from a shadow - light does not
|
|
26
|
+
// fall downwards. Bare `.mw-glow` rides along on primary, because the brand
|
|
27
|
+
// colour is what a glow means unless it says otherwise.
|
|
28
|
+
@each $name, $col in $semantic-colors {
|
|
29
|
+
$selector: '.mw-glow-#{$name}';
|
|
30
|
+
|
|
31
|
+
@if $name == 'primary' {
|
|
32
|
+
$selector: '.mw-glow, #{$selector}';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#{$selector} {
|
|
36
|
+
box-shadow:
|
|
37
|
+
0 0 6px color-mix(in srgb, #{$col} 45%, transparent),
|
|
38
|
+
0 0 26px color-mix(in srgb, #{$col} 28%, transparent);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
18
41
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// sizes are right under a pointer and too small under a thumb. Coarse *or*
|
|
6
6
|
// narrow, because a tablet in landscape is wide and still finger-operated.
|
|
7
7
|
// Loaded last, so these win without extra specificity.
|
|
8
|
-
@media (pointer: coarse), (
|
|
8
|
+
@media (pointer: coarse), (width <= #{breakpoint('md')}) {
|
|
9
9
|
// Padding and line-height add up to ~35px, under the 44px a thumb needs. Only
|
|
10
10
|
// the height grows: the padding sets the label's relationship to the edges.
|
|
11
11
|
.mw-btn {
|
|
@@ -31,17 +31,30 @@
|
|
|
31
31
|
// the modal, which genuinely float above content and keep their shadow - in a
|
|
32
32
|
// flat page they are the only two things that should cast one.
|
|
33
33
|
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
:root.mw-shadows-flat,
|
|
39
|
-
:root.mw-shadows-flat .mw-theme-light {
|
|
34
|
+
// One selector, unlike mw-surfaces-flush below: the ramp is no longer declared
|
|
35
|
+
// per theme, so there is no copy further down the tree to shadow this one. The
|
|
36
|
+
// theme reaches it through --mw-shadow-near/-far instead - see elevation().
|
|
37
|
+
:root.mw-shadows-flat {
|
|
40
38
|
--mw-elevation-1: none;
|
|
41
39
|
--mw-elevation-2: none;
|
|
42
40
|
--mw-elevation-3: none;
|
|
43
41
|
}
|
|
44
42
|
|
|
43
|
+
// Cards, panels and the footer give up their own tone and sit flush on the
|
|
44
|
+
// page, told apart by their line alone. That line then has to carry them:
|
|
45
|
+
// --mw-border is a neighbouring shade of the surface and reads as nothing once
|
|
46
|
+
// the surface *is* the page, so it is redrawn from the ink instead.
|
|
47
|
+
//
|
|
48
|
+
// Theme-bound tokens, and those *are* re-declared on <body> when the toggle puts
|
|
49
|
+
// .mw-theme-light there - a value written on :root alone would be shadowed for
|
|
50
|
+
// the whole body subtree and the switch would do nothing in light mode.
|
|
51
|
+
:root.mw-surfaces-flush,
|
|
52
|
+
:root.mw-surfaces-flush .mw-theme-light {
|
|
53
|
+
--mw-card-background: var(--mw-page-background);
|
|
54
|
+
--mw-footer-background: var(--mw-page-background);
|
|
55
|
+
--mw-border: color-mix(in srgb, var(--mw-text-color) 20%, transparent);
|
|
56
|
+
}
|
|
57
|
+
|
|
45
58
|
// The diagonal hatch behind an alternating section, dropped. Written on the
|
|
46
59
|
// section and not as a token on :root: --mw-page-background is a theme alias
|
|
47
60
|
// that only becomes the light one further down the tree, so a copy taken up
|
|
@@ -57,6 +70,35 @@
|
|
|
57
70
|
border-radius: 999px;
|
|
58
71
|
}
|
|
59
72
|
|
|
73
|
+
// The other end of the same axis. Not --mw-radius-scale, which squares off the
|
|
74
|
+
// whole page - a page can want its cards round and its buttons cut.
|
|
75
|
+
:root.mw-btn-square .mw-btn {
|
|
76
|
+
border-radius: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// A raised edge under the fill that the button sinks onto when pressed. The
|
|
80
|
+
// four solid variants only: outline, ghost and link have no fill to darken.
|
|
81
|
+
//
|
|
82
|
+
// Mixed toward black rather than taken from --mw-*-color-hover, which moves
|
|
83
|
+
// toward the light in one theme and away from it in the other - an edge has to
|
|
84
|
+
// be darker than its face in both.
|
|
85
|
+
:root.mw-btn-tactile {
|
|
86
|
+
@each $name in ('primary', 'secondary', 'danger', 'success') {
|
|
87
|
+
.mw-btn-#{$name} {
|
|
88
|
+
box-shadow: 0
|
|
89
|
+
3px
|
|
90
|
+
0
|
|
91
|
+
color-mix(in srgb, var(--mw-#{$name}-color) 72%, #000);
|
|
92
|
+
|
|
93
|
+
// Travels the full height of the edge, where the base button moves 1px
|
|
94
|
+
&:active:not(:disabled) {
|
|
95
|
+
transform: translateY(3px);
|
|
96
|
+
box-shadow: none;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
60
102
|
// Tinted glass: a translucent wash with a vertical ramp and a specular line
|
|
61
103
|
// along the top edge, which is what gives the button its thickness.
|
|
62
104
|
//
|
|
@@ -117,4 +159,71 @@
|
|
|
117
159
|
letter-spacing: 0.045em;
|
|
118
160
|
}
|
|
119
161
|
}
|
|
162
|
+
|
|
163
|
+
// The other axis to --mw-root-font-size, which zooms the whole page: there
|
|
164
|
+
// the layout is the same layout, larger. This moves the padding inside a
|
|
165
|
+
// surface and leaves the type alone, so a dense screen reads as well as a
|
|
166
|
+
// roomy one and only fits more on.
|
|
167
|
+
//
|
|
168
|
+
// --mw-section-padding-block is deliberately untouched: section spacing is
|
|
169
|
+
// its own switch, and both writing it would have the panel print a setup that
|
|
170
|
+
// contradicts itself. Steps along the spacing scale rather than free values,
|
|
171
|
+
// because that scale is what every other measure is built from - two of them
|
|
172
|
+
// down for compact, where the point is to fit more on screen, one up for
|
|
173
|
+
// roomy, where a second step would only look loose.
|
|
174
|
+
:root.mw-density-compact {
|
|
175
|
+
--mw-control-height-sm: 1.5rem;
|
|
176
|
+
--mw-control-height: 1.75rem;
|
|
177
|
+
--mw-control-height-lg: 2rem;
|
|
178
|
+
|
|
179
|
+
.mw-card-body {
|
|
180
|
+
padding: spacing('4') spacing('2') spacing('3');
|
|
181
|
+
|
|
182
|
+
@container mw-card (width >= #{$mw-card-wide}) {
|
|
183
|
+
padding: spacing('5') spacing('3') spacing('4');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.mw-panel-header,
|
|
188
|
+
.mw-panel-body {
|
|
189
|
+
padding: spacing('2') spacing('3');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
:root.mw-density-roomy {
|
|
194
|
+
--mw-control-height-sm: 2.25rem;
|
|
195
|
+
--mw-control-height: 2.5rem;
|
|
196
|
+
--mw-control-height-lg: 2.75rem;
|
|
197
|
+
|
|
198
|
+
.mw-card-body {
|
|
199
|
+
padding: spacing('7') spacing('5') spacing('6');
|
|
200
|
+
|
|
201
|
+
@container mw-card (width >= #{$mw-card-wide}) {
|
|
202
|
+
padding: spacing('8') spacing('6') spacing('7');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.mw-panel-header,
|
|
207
|
+
.mw-panel-body {
|
|
208
|
+
padding: spacing('5') spacing('6');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
:root.mw-links-underline {
|
|
213
|
+
.mw-link,
|
|
214
|
+
.mw-link-muted,
|
|
215
|
+
.mw-btn-link {
|
|
216
|
+
// The longhand, because the `text-decoration` shorthand resets
|
|
217
|
+
// text-decoration-thickness along with it and would drop the 1.5px
|
|
218
|
+
// link-look() draws the line at.
|
|
219
|
+
text-decoration-line: underline;
|
|
220
|
+
|
|
221
|
+
// The underline was the hover signal and is now the resting state, so the
|
|
222
|
+
// weight takes over: .mw-link carries no colour change of its own and
|
|
223
|
+
// would otherwise go completely dead under the pointer.
|
|
224
|
+
&:hover:not(:disabled) {
|
|
225
|
+
text-decoration-thickness: 3px;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
120
229
|
}
|