maverick-wave 5.26.0 → 5.27.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/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "maverick-wave",
3
- "version": "5.26.0",
3
+ "version": "5.27.0",
4
4
  "config": {
5
- "version_short": "5.26"
5
+ "version_short": "5.27"
6
6
  },
7
7
  "description": "A lightweight, modern CSS framework for building responsive websites with elegance and speed.",
8
8
  "main": "src/js/main.js",
package/scripts/verify.js CHANGED
@@ -109,6 +109,10 @@ for (const t of [...tokensDefined].sort()) {
109
109
 
110
110
  const classesInCss = new Set(all(css, /\.(mw-[a-z0-9-]+)/g));
111
111
 
112
+ // Keyframes carry the same prefix and get named in the docs, but they are not
113
+ // classes - and one the docs name without the CSS having it still has to fail.
114
+ const keyframesInCss = new Set(all(css, /@keyframes\s+(mw-[a-z0-9-]+)/g));
115
+
112
116
  // Classes the JS adds at runtime, or queries as a hook, count as legitimate
113
117
  // targets - including selector strings like '.mw-foo' and '[class~="mw-foo"]'
114
118
  const classesInJs = new Set(all(js, /\.?(mw-[a-z0-9-]+)/g));
@@ -130,7 +134,12 @@ for (const c of all(docs, /[`."'\s](mw-[a-z0-9-]+)/g)) {
130
134
  }
131
135
 
132
136
  for (const [c, where] of [...classesInMarkup].sort()) {
133
- if (classesInCss.has(c) || classesInJs.has(c) || CLASS_ALLOWLIST.has(c)) {
137
+ if (
138
+ classesInCss.has(c) ||
139
+ classesInJs.has(c) ||
140
+ keyframesInCss.has(c) ||
141
+ CLASS_ALLOWLIST.has(c)
142
+ ) {
134
143
  continue;
135
144
  }
136
145
  errors.push(`class used in ${where} but not generated by the CSS: .${c}`);
@@ -8,66 +8,66 @@
8
8
  <div>
9
9
  <h4 class="mw-mb-2">Basic Tiles in 3 Columns</h4>
10
10
  <div class="mw-tiles">
11
- <div class="mw-tile">
11
+ <a href="#" class="mw-tile">
12
12
  <h3 class="mw-tile-header">Project Management</h3>
13
13
  <div class="mw-tile-body">
14
14
  <p>Organize tasks and track project progress</p>
15
15
  <p>Collaborate with team members efficiently</p>
16
16
  </div>
17
17
  <div class="mw-tile-footer">Last updated: 2024-12-15</div>
18
- </div>
18
+ </a>
19
19
 
20
- <div class="mw-tile">
20
+ <a href="#" class="mw-tile">
21
21
  <h3 class="mw-tile-header">Analytics Dashboard</h3>
22
22
  <div class="mw-tile-body">
23
23
  <p>Real-time data visualization and insights</p>
24
24
  <p>Track KPIs and performance metrics</p>
25
25
  </div>
26
26
  <div class="mw-tile-footer">Last updated: 2025-01-02</div>
27
- </div>
27
+ </a>
28
28
 
29
- <div class="mw-tile">
29
+ <a href="#" class="mw-tile">
30
30
  <h3 class="mw-tile-header">Customer Support</h3>
31
31
  <div class="mw-tile-body">
32
32
  <p>24/7 help desk and ticket management</p>
33
33
  <p>Live chat and knowledge base access</p>
34
34
  </div>
35
35
  <div class="mw-tile-footer">Last updated: 2024-11-23</div>
36
- </div>
36
+ </a>
37
37
 
38
- <div class="mw-tile">
38
+ <a href="#" class="mw-tile">
39
39
  <h3 class="mw-tile-header">Document Management</h3>
40
40
  <div class="mw-tile-body">
41
41
  <p>Secure file storage and version control</p>
42
42
  <p>Easy sharing and collaboration tools</p>
43
43
  </div>
44
44
  <div class="mw-tile-footer">Last updated: 2024-12-30</div>
45
- </div>
45
+ </a>
46
46
 
47
- <div class="mw-tile">
47
+ <a href="#" class="mw-tile">
48
48
  <h3 class="mw-tile-header">Billing & Invoices</h3>
49
49
  <div class="mw-tile-body">
50
50
  <p>Automated invoicing and payment tracking</p>
51
51
  <p>Financial reporting and tax preparation</p>
52
52
  </div>
53
53
  <div class="mw-tile-footer">Last updated: 2025-01-01</div>
54
- </div>
54
+ </a>
55
55
 
56
- <div class="mw-tile">
56
+ <a href="#" class="mw-tile">
57
57
  <h3 class="mw-tile-header">User Management</h3>
58
58
  <div class="mw-tile-body">
59
59
  <p>Role-based access control and permissions</p>
60
60
  <p>User authentication and security settings</p>
61
61
  </div>
62
62
  <div class="mw-tile-footer">Last updated: 2024-12-28</div>
63
- </div>
63
+ </a>
64
64
  </div>
65
65
  </div>
66
66
 
67
67
  <div>
68
68
  <h4 class="mw-mb-2">Basic Tiles with Images in 2 Columns</h4>
69
69
  <div class="mw-tiles mw-tiles-2col">
70
- <div class="mw-tile">
70
+ <a href="#" class="mw-tile">
71
71
  <div class="mw-tile-img">
72
72
  <img
73
73
  src="images/tile-ecommerce.svg"
@@ -81,9 +81,9 @@
81
81
  <p>Inventory tracking and order fulfillment</p>
82
82
  </div>
83
83
  <div class="mw-tile-footer">Last updated: 2024-12-15</div>
84
- </div>
84
+ </a>
85
85
 
86
- <div class="mw-tile">
86
+ <a href="#" class="mw-tile">
87
87
  <div class="mw-tile-img">
88
88
  <img
89
89
  src="images/tile-marketing.svg"
@@ -97,91 +97,91 @@
97
97
  <p>Social media scheduling and analytics</p>
98
98
  </div>
99
99
  <div class="mw-tile-footer">Last updated: 2025-01-02</div>
100
- </div>
100
+ </a>
101
101
  </div>
102
102
  </div>
103
103
 
104
104
  <div>
105
105
  <h4 class="mw-mb-2">Small Tiles in 4 Columns</h4>
106
106
  <div class="mw-tiles mw-tiles-4col">
107
- <div class="mw-tile mw-tile-sm">
107
+ <a href="#" class="mw-tile mw-tile-sm">
108
108
  <h3 class="mw-tile-header">API Documentation</h3>
109
109
  <div class="mw-tile-body">
110
110
  <p>REST API reference guide</p>
111
111
  <p>Code examples and tutorials</p>
112
112
  </div>
113
113
  <div class="mw-tile-footer">Last updated: 2025-01-01</div>
114
- </div>
114
+ </a>
115
115
 
116
- <div class="mw-tile mw-tile-sm">
116
+ <a href="#" class="mw-tile mw-tile-sm">
117
117
  <h3 class="mw-tile-header">Security Center</h3>
118
118
  <div class="mw-tile-body">
119
119
  <p>Two-factor authentication</p>
120
120
  <p>Security audit logs</p>
121
121
  </div>
122
122
  <div class="mw-tile-footer">Last updated: 2024-12-31</div>
123
- </div>
123
+ </a>
124
124
 
125
- <div class="mw-tile mw-tile-sm">
125
+ <a href="#" class="mw-tile mw-tile-sm">
126
126
  <h3 class="mw-tile-header">Backup & Recovery</h3>
127
127
  <div class="mw-tile-body">
128
128
  <p>Automated daily backups</p>
129
129
  <p>One-click data restoration</p>
130
130
  </div>
131
131
  <div class="mw-tile-footer">Last updated: 2024-12-29</div>
132
- </div>
132
+ </a>
133
133
 
134
- <div class="mw-tile mw-tile-sm">
134
+ <a href="#" class="mw-tile mw-tile-sm">
135
135
  <h3 class="mw-tile-header">Performance Monitor</h3>
136
136
  <div class="mw-tile-body">
137
137
  <p>Server uptime: 99.9%</p>
138
138
  <p>Response time: 150ms</p>
139
139
  </div>
140
140
  <div class="mw-tile-footer">Last updated: 2025-01-02</div>
141
- </div>
141
+ </a>
142
142
 
143
- <div class="mw-tile mw-tile-sm">
143
+ <a href="#" class="mw-tile mw-tile-sm">
144
144
  <h3 class="mw-tile-header">Integration Hub</h3>
145
145
  <div class="mw-tile-body">
146
146
  <p>Connect third-party apps</p>
147
147
  <p>Webhook configurations</p>
148
148
  </div>
149
149
  <div class="mw-tile-footer">Last updated: 2024-12-27</div>
150
- </div>
150
+ </a>
151
151
 
152
- <div class="mw-tile mw-tile-sm">
152
+ <a href="#" class="mw-tile mw-tile-sm">
153
153
  <h3 class="mw-tile-header">Mobile App</h3>
154
154
  <div class="mw-tile-body">
155
155
  <p>iOS and Android apps</p>
156
156
  <p>Offline sync capabilities</p>
157
157
  </div>
158
158
  <div class="mw-tile-footer">Last updated: 2024-12-25</div>
159
- </div>
159
+ </a>
160
160
 
161
- <div class="mw-tile mw-tile-sm">
161
+ <a href="#" class="mw-tile mw-tile-sm">
162
162
  <h3 class="mw-tile-header">Training Center</h3>
163
163
  <div class="mw-tile-body">
164
164
  <p>Video tutorials available</p>
165
165
  <p>Certification programs</p>
166
166
  </div>
167
167
  <div class="mw-tile-footer">Last updated: 2025-01-01</div>
168
- </div>
168
+ </a>
169
169
 
170
- <div class="mw-tile mw-tile-sm">
170
+ <a href="#" class="mw-tile mw-tile-sm">
171
171
  <h3 class="mw-tile-header">System Status</h3>
172
172
  <div class="mw-tile-body">
173
173
  <p>All systems operational</p>
174
174
  <p>Last incident: None</p>
175
175
  </div>
176
176
  <div class="mw-tile-footer">Last updated: 2024-12-30</div>
177
- </div>
177
+ </a>
178
178
  </div>
179
179
  </div>
180
180
 
181
181
  <div>
182
182
  <h4 class="mw-mb-2">Large Tiles</h4>
183
183
  <div class="mw-tiles">
184
- <div class="mw-tile mw-tile-lg">
184
+ <a href="#" class="mw-tile mw-tile-lg">
185
185
  <div class="mw-tile-img">
186
186
  <img
187
187
  src="images/tile-cloud.svg"
@@ -200,9 +200,9 @@
200
200
  </p>
201
201
  </div>
202
202
  <div class="mw-tile-footer">Last updated: 2024-12-28</div>
203
- </div>
203
+ </a>
204
204
 
205
- <div class="mw-tile mw-tile-lg">
205
+ <a href="#" class="mw-tile mw-tile-lg">
206
206
  <div class="mw-tile-img">
207
207
  <img
208
208
  src="images/tile-analytics.svg"
@@ -222,9 +222,9 @@
222
222
  </p>
223
223
  </div>
224
224
  <div class="mw-tile-footer">Last updated: 2024-12-31</div>
225
- </div>
225
+ </a>
226
226
 
227
- <div class="mw-tile mw-tile-lg">
227
+ <a href="#" class="mw-tile mw-tile-lg">
228
228
  <div class="mw-tile-img">
229
229
  <img
230
230
  src="images/tile-enterprise.svg"
@@ -241,7 +241,7 @@
241
241
  </p>
242
242
  </div>
243
243
  <div class="mw-tile-footer">Last updated: 2024-12-23</div>
244
- </div>
244
+ </a>
245
245
  </div>
246
246
  </div>
247
247
  </div>
@@ -131,13 +131,22 @@
131
131
  // header height
132
132
  --mw-header-height: #{$header-height};
133
133
 
134
- // Read by the anchor offset of anything the sticky section nav can cover
135
- --mw-section-nav-height: 3.7rem;
134
+ // Read by the anchor offset of anything the sticky section nav can cover.
135
+ // The strip at its tallest: a 2.75rem button under a thumb plus its two
136
+ // 0.5rem paddings. Rounded up rather than down - a pointer gets 2px of
137
+ // slack, and the offset may overshoot but must not undershoot.
138
+ --mw-section-nav-height: 3.75rem;
136
139
 
137
140
  // The anchor scroll offset is calculated from it, so a taller ribbon raises
138
141
  // this token rather than fighting the offset
139
142
  --mw-announcement-height: 2.7rem;
140
143
 
144
+ // What each layer of sticky chrome below the header adds to the scroll
145
+ // offset in the reset. A length and not a bare 0 - calc() cannot add a
146
+ // unitless one.
147
+ --mw-announcement-offset: 0px;
148
+ --mw-section-nav-offset: 0px;
149
+
141
150
  // Fluid rather than stepped: ~24px at 375px up to 64px, where the 1200px cap
142
151
  // takes over. Stepping at a breakpoint makes the container jump *backwards*
143
152
  // there, because the gutter grows faster than the viewport does.
@@ -160,11 +169,12 @@
160
169
  --mw-section-padding-compact: #{spacing('8')};
161
170
  --mw-section-padding-airy: #{spacing('12')};
162
171
  // The third regime beside the stepped default and the two stepped presets:
163
- // spacing that grows with the screen. It starts at the value a phone already
164
- // gets below `sm` and reaches the airy preset at `xl`, so a desktop pushes
165
- // less content past per wheel notch while the phone carries none of that air.
166
- // Needs no steps of its own - the ramp is the steps.
167
- --mw-section-padding-fluid: #{fluid(spacing('7'), spacing('12'), $to: 'xl')};
172
+ // spacing that grows with the screen. Both ends sit beside the spacing scale
173
+ // rather than on it: the nearest steps are a phone value the default already
174
+ // has and a desktop value the airy preset already is, and a ramp that ends
175
+ // where a preset ends is a preset. Needs no steps of its own - the ramp is
176
+ // the steps.
177
+ --mw-section-padding-fluid: #{fluid(35px, 65px, $to: 'xl')};
168
178
  // The section head: the gap it leaves to the content below, the space
169
179
  // between its rule and the title, and the mark sitting on that rule.
170
180
  //
@@ -14,7 +14,13 @@
14
14
  font-size: var(--mw-root-font-size);
15
15
  scroll-behavior: smooth;
16
16
  min-width: 320px;
17
- scroll-padding-top: var(--mw-header-height);
17
+ // Each layer of sticky chrome contributes its own term, so a page carrying
18
+ // both a ribbon and a section nav reserves for both - two rules setting one
19
+ // offset would have the later layer silently win instead.
20
+ scroll-padding-top: calc(
21
+ var(--mw-header-height) + var(--mw-announcement-offset) +
22
+ var(--mw-section-nav-offset)
23
+ );
18
24
  -webkit-text-size-adjust: 100%;
19
25
  text-size-adjust: 100%;
20
26
  @include scrollbar(var(--mw-border), transparent);
@@ -60,9 +60,7 @@
60
60
  // page without a ribbon keeps the plain offset - and a static ribbon does not
61
61
  // count, it scrolls with the content.
62
62
  html:has(.mw-announcement:not(.mw-announcement-static)) {
63
- scroll-padding-top: calc(
64
- var(--mw-header-height) + var(--mw-announcement-height)
65
- );
63
+ --mw-announcement-offset: var(--mw-announcement-height);
66
64
  }
67
65
 
68
66
  // On a phone the line wraps and the ribbon grows - the height token follows,
@@ -8,13 +8,14 @@
8
8
  // One-shot entrance, not a loop, so it belongs on the scale. It ran for
9
9
  // 1.6s before - long enough that the reader is into the second paragraph
10
10
  // while the page is still arriving.
11
- animation: pageReveal var(--mw-duration-slower) var(--mw-ease-out) forwards;
11
+ animation: mw-page-reveal var(--mw-duration-slower) var(--mw-ease-out)
12
+ forwards;
12
13
  border-radius: radius('sm') radius('2xl') radius('sm') radius('2xl');
13
14
  box-shadow:
14
15
  var(--mw-border) 0 30px 60px -18px inset,
15
16
  var(--mw-border) 0 18px 36px -18px inset;
16
17
 
17
- @keyframes pageReveal {
18
+ @keyframes mw-page-reveal {
18
19
  0% {
19
20
  opacity: 0;
20
21
  transform: translateY(-30px) rotateX(10deg);
@@ -81,10 +82,10 @@
81
82
  margin-bottom: spacing('4');
82
83
  font-size: font-size('xl');
83
84
  box-shadow: var(--mw-elevation-2);
84
- animation: iconFlip var(--mw-duration-slower) var(--mw-ease-out)
85
+ animation: mw-icon-flip var(--mw-duration-slower) var(--mw-ease-out)
85
86
  forwards;
86
87
 
87
- @keyframes iconFlip {
88
+ @keyframes mw-icon-flip {
88
89
  0% {
89
90
  transform: rotateY(90deg);
90
91
  }
@@ -280,13 +280,13 @@
280
280
  flex-shrink: 0;
281
281
  text-wrap: balance;
282
282
 
283
- /* push the last element all the way right - a single one included */
283
+ // The last element goes right whether it has company or not, so a lone
284
+ // button sits where the confirming one sits in a pair
284
285
  > *:last-child {
285
286
  margin-left: auto;
286
287
  text-align: right;
287
288
  }
288
289
 
289
- // Ensure buttons maintain their size
290
290
  .mw-btn {
291
291
  flex-shrink: 0;
292
292
  }
@@ -19,10 +19,12 @@
19
19
  gap: spacing('1') spacing('4');
20
20
  }
21
21
 
22
- // Sized rather than auto, so the values line up under each other however
23
- // long the words in front of them are
22
+ // A floor rather than a fixed size, so the values line up under each other
23
+ // however long the words in front of them are - and a label longer than the
24
+ // column still gets its room instead of running into the value beside it
24
25
  &-label {
25
- flex: 0 0 5rem;
26
+ flex: 0 0 auto;
27
+ min-width: 5rem;
26
28
  color: var(--mw-text-muted-color);
27
29
  }
28
30
  }
@@ -10,11 +10,11 @@
10
10
  height: 4px;
11
11
  background: var(--mw-warning-color);
12
12
  z-index: z-index('modal')-10;
13
- animation: pulse-indicator motion(4s) infinite;
13
+ animation: mw-pulse-indicator motion(4s) infinite;
14
14
  }
15
15
 
16
16
  // Keyframes for the pulsing indicator
17
- @keyframes pulse-indicator {
17
+ @keyframes mw-pulse-indicator {
18
18
  0% {
19
19
  opacity: 0.5;
20
20
  box-shadow: 0 0 3px var(--mw-warning-color);
@@ -1,6 +1,14 @@
1
1
  @use '../abstracts' as *;
2
2
 
3
3
  @layer mw.components {
4
+ // -scrollable is the older spelling of -max-height-md
5
+ $_mw-panel-heights: (
6
+ 'max-height-sm': 300px,
7
+ 'max-height-md': 500px,
8
+ 'max-height-lg': 700px,
9
+ 'scrollable': 500px,
10
+ );
11
+
4
12
  .mw-panel {
5
13
  background: var(--mw-card-background);
6
14
  @include surface(2px);
@@ -8,13 +16,15 @@
8
16
  overflow: hidden;
9
17
  display: flex;
10
18
  flex-direction: column;
11
- min-height: 100%;
12
- margin: spacing('1');
13
19
 
14
20
  &-header {
15
21
  padding: spacing('4') spacing('5');
16
22
  border-bottom: 1px solid var(--mw-border-accent);
17
23
  display: flex;
24
+ // A title with an action beside it runs out of room on a phone long
25
+ // before the title runs out of words
26
+ flex-wrap: wrap;
27
+ gap: spacing('3');
18
28
  justify-content: space-between;
19
29
  align-items: center;
20
30
  margin: spacing('0');
@@ -48,7 +58,6 @@
48
58
  gap: spacing('3');
49
59
  }
50
60
 
51
- // Panel variants
52
61
  &-primary {
53
62
  .mw-panel-header {
54
63
  background: var(--mw-primary-color);
@@ -72,56 +81,13 @@
72
81
  @include corner-accent(2px, 'bottom');
73
82
  }
74
83
 
75
- // Scrollable variant for fixed height
76
- &-scrollable {
77
- max-height: 500px;
78
-
79
- .mw-panel-body {
80
- overflow-y: auto;
81
- max-height: calc(500px - #{2 * spacing('4')} - 2px);
82
- }
83
- }
84
-
85
- // Scrollable variants for max height
86
- &-max-height {
87
- &-sm {
88
- max-height: 300px;
89
- min-height: 0;
90
- align-self: start;
91
- .mw-panel-body {
92
- max-height: calc(300px - #{2 * spacing('4')} - 2px);
93
- overflow-y: auto;
94
- }
95
- }
96
-
97
- &-md {
98
- max-height: 500px;
99
- min-height: 0;
100
- align-self: start;
101
- .mw-panel-body {
102
- max-height: calc(500px - #{2 * spacing('4')} - 2px);
103
- overflow-y: auto;
104
- }
105
- }
106
-
107
- &-lg {
108
- max-height: 700px;
109
- min-height: 0;
84
+ // Only the cap - the body already scrolls and already takes what the header
85
+ // and footer leave it. `align-self` because a grid row stretches its items
86
+ // first, and a stretched panel reaches the cap from above whatever it says.
87
+ @each $name, $height in $_mw-panel-heights {
88
+ &-#{$name} {
89
+ max-height: $height;
110
90
  align-self: start;
111
- .mw-panel-body {
112
- max-height: calc(700px - #{2 * spacing('4')} - 2px);
113
- overflow-y: auto;
114
- }
115
- }
116
- }
117
-
118
- @include media-down('sm') {
119
- font-size: font-size('sm');
120
-
121
- &-header {
122
- h3 {
123
- font-size: font-size('sm');
124
- }
125
91
  }
126
92
  }
127
93
  }
@@ -132,7 +132,7 @@
132
132
  display: block;
133
133
  // 1.1s to reveal a tab panel means a second of blank space after every
134
134
  // click. A panel switch is a state change, not an entrance.
135
- animation: fadeIn var(--mw-duration-base) var(--mw-ease-out);
135
+ animation: mw-tabs-fade var(--mw-duration-base) var(--mw-ease-out);
136
136
  }
137
137
  }
138
138
 
@@ -281,7 +281,7 @@
281
281
  }
282
282
  }
283
283
 
284
- @keyframes fadeIn {
284
+ @keyframes mw-tabs-fade {
285
285
  from {
286
286
  opacity: 0;
287
287
  }