maverick-wave 4.9.4 → 4.11.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.
Files changed (117) hide show
  1. package/.claude/skills/maverick-wave/SKILL.md +112 -12
  2. package/.claude/skills/maverick-wave/references/components.md +152 -4
  3. package/.claude/skills/maverick-wave/references/forms.md +26 -0
  4. package/.claude/skills/maverick-wave/references/javascript.md +34 -27
  5. package/.claude/skills/maverick-wave/references/layout.md +38 -3
  6. package/.claude/skills/maverick-wave/references/theming.md +33 -7
  7. package/CHANGELOG.md +6 -0
  8. package/README.md +79 -4
  9. package/index.html +16 -0
  10. package/maverick-wave.min.css +3 -3
  11. package/maverick-wave.min.js +1 -1
  12. package/package.json +2 -2
  13. package/src/js/main.js +71 -1
  14. package/src/partials/accordions-container.html +5 -0
  15. package/src/partials/alerts-container.html +5 -0
  16. package/src/partials/avatars-container.html +5 -0
  17. package/src/partials/badges-container.html +114 -0
  18. package/src/partials/blog-posts-container.html +5 -0
  19. package/src/partials/breadcrumbs-container.html +1 -1
  20. package/src/partials/button-bar-container.html +5 -0
  21. package/src/partials/buttons-container.html +84 -0
  22. package/src/partials/calendar-container.html +1 -1
  23. package/src/partials/cards-container.html +5 -0
  24. package/src/partials/code-container.html +6 -0
  25. package/src/partials/colors-container.html +1 -1
  26. package/src/partials/coming-soon-container.html +4 -0
  27. package/src/partials/divider-container.html +4 -0
  28. package/src/partials/dropdown-container.html +119 -0
  29. package/src/partials/empty-state-container.html +5 -0
  30. package/src/partials/form-container.html +5 -0
  31. package/src/partials/form-elements-container.html +5 -0
  32. package/src/partials/form-field-container.html +5 -0
  33. package/src/partials/gallery-container.html +5 -0
  34. package/src/partials/get-started-container.html +16 -4
  35. package/src/partials/header-container.html +6 -2
  36. package/src/partials/header-utilities-container.html +8 -2
  37. package/src/partials/html-lists-container.html +5 -0
  38. package/src/partials/info-container.html +4 -0
  39. package/src/partials/input-group-container.html +5 -0
  40. package/src/partials/item-lists-container.html +5 -0
  41. package/src/partials/kanban-container.html +1 -1
  42. package/src/partials/kbd-container.html +63 -0
  43. package/src/partials/meta-info-container.html +5 -0
  44. package/src/partials/pagination-container.html +1 -1
  45. package/src/partials/panels-container.html +4 -0
  46. package/src/partials/progress-container.html +4 -0
  47. package/src/partials/ratings-container.html +1 -1
  48. package/src/partials/skeleton-container.html +5 -0
  49. package/src/partials/spinners-container.html +5 -1
  50. package/src/partials/stepper-container.html +4 -0
  51. package/src/partials/tables-container.html +7 -0
  52. package/src/partials/tabs-container.html +35 -13
  53. package/src/partials/tags-container.html +5 -0
  54. package/src/partials/tiles-container.html +1 -1
  55. package/src/partials/typography-container.html +5 -0
  56. package/src/partials/utilities-container.html +153 -0
  57. package/src/scss/abstracts/_mixins.scss +176 -0
  58. package/src/scss/abstracts/_variables.scss +193 -5
  59. package/src/scss/base/_base.scss +103 -2
  60. package/src/scss/base/_reset.scss +43 -1
  61. package/src/scss/base/_typography.scss +47 -0
  62. package/src/scss/components/_accordions.scss +11 -1
  63. package/src/scss/components/_alerts.scss +3 -3
  64. package/src/scss/components/_avatars.scss +27 -6
  65. package/src/scss/components/_badge.scss +157 -0
  66. package/src/scss/components/_blog-post.scss +10 -7
  67. package/src/scss/components/_breadcrumbs.scss +11 -2
  68. package/src/scss/components/_button-bar.scss +9 -2
  69. package/src/scss/components/_buttons.scss +133 -17
  70. package/src/scss/components/_calendar.scss +13 -2
  71. package/src/scss/components/_cards.scss +12 -5
  72. package/src/scss/components/_code.scss +15 -0
  73. package/src/scss/components/_coming-soon.scss +5 -2
  74. package/src/scss/components/_content-slider.scss +1 -1
  75. package/src/scss/components/_dropdown.scss +219 -0
  76. package/src/scss/components/_gallery.scss +17 -8
  77. package/src/scss/components/_index.scss +3 -0
  78. package/src/scss/components/_info.scss +14 -8
  79. package/src/scss/components/_kanban.scss +40 -6
  80. package/src/scss/components/_kbd.scss +43 -0
  81. package/src/scss/components/_lists.scss +26 -23
  82. package/src/scss/components/_modals.scss +71 -6
  83. package/src/scss/components/_pagination.scss +4 -3
  84. package/src/scss/components/_panels.scss +13 -14
  85. package/src/scss/components/_progress.scss +1 -1
  86. package/src/scss/components/_segmented.scss +8 -4
  87. package/src/scss/components/_stepper.scss +3 -3
  88. package/src/scss/components/_tables.scss +5 -8
  89. package/src/scss/components/_tabs.scss +22 -3
  90. package/src/scss/components/_tags.scss +1 -2
  91. package/src/scss/components/_techstack-bucket.scss +8 -5
  92. package/src/scss/components/_theme-toggle.scss +16 -8
  93. package/src/scss/components/_tiles.scss +14 -4
  94. package/src/scss/components/_timelines.scss +9 -6
  95. package/src/scss/components/_toasts.scss +1 -1
  96. package/src/scss/form-elements/_checkbox.scss +2 -1
  97. package/src/scss/form-elements/_form.scss +2 -2
  98. package/src/scss/form-elements/_input-group.scss +30 -1
  99. package/src/scss/form-elements/_input.scss +10 -10
  100. package/src/scss/form-elements/_login.scss +1 -1
  101. package/src/scss/form-elements/_radio.scss +4 -3
  102. package/src/scss/form-elements/_select.scss +9 -10
  103. package/src/scss/form-elements/_slider.scss +11 -11
  104. package/src/scss/form-elements/_textarea.scss +5 -8
  105. package/src/scss/form-elements/_toggle.scss +6 -5
  106. package/src/scss/layout/_footer.scss +14 -7
  107. package/src/scss/layout/_header.scss +18 -17
  108. package/src/scss/layout/_home.scss +1 -1
  109. package/src/scss/layout/_main.scss +6 -6
  110. package/src/scss/layout/_section.scss +7 -4
  111. package/src/scss/utilities/_accessibility.scss +38 -0
  112. package/src/scss/utilities/_aspect.scss +27 -0
  113. package/src/scss/utilities/_display.scss +52 -0
  114. package/src/scss/utilities/_elevation.scss +16 -0
  115. package/src/scss/utilities/_index.scss +2 -0
  116. package/src/scss/utilities/_text.scss +63 -0
  117. package/src/scss/utilities/_touch-targets.scss +63 -0
@@ -1,6 +1,7 @@
1
1
  @forward 'accordions';
2
2
  @forward 'alerts';
3
3
  @forward 'avatars';
4
+ @forward 'badge';
4
5
  @forward 'blog-post';
5
6
  @forward 'buttons';
6
7
  @forward 'button-bar';
@@ -11,10 +12,12 @@
11
12
  @forward 'coming-soon';
12
13
  @forward 'content-slider';
13
14
  @forward 'divider';
15
+ @forward 'dropdown';
14
16
  @forward 'empty-state';
15
17
  @forward 'gallery';
16
18
  @forward 'info';
17
19
  @forward 'kanban';
20
+ @forward 'kbd';
18
21
  @forward 'lists';
19
22
  @forward 'localhost-indicator';
20
23
  @forward 'meta-info';
@@ -23,19 +23,28 @@ $_mw-info-colors: (
23
23
  border: 1px solid var(--mw-border);
24
24
  border-radius: radius('md');
25
25
  transition:
26
- transform 0.3s ease,
27
- box-shadow 0.3s ease;
26
+ transform var(--mw-duration-base) var(--mw-ease-out),
27
+ box-shadow var(--mw-duration-base) var(--mw-ease-out);
28
28
  cursor: default;
29
29
  text-decoration: none;
30
30
 
31
31
  &:hover {
32
+ box-shadow: var(--mw-elevation-3);
33
+ }
34
+
35
+ @include hover {
32
36
  transform: translateY(-2px);
33
- box-shadow: -1px 6px 9px var(--mw-shadow);
34
37
  }
35
38
 
36
39
  // Interactive variant
37
40
  &-clickable {
38
41
  cursor: pointer;
42
+ @include tappable;
43
+
44
+ &:active {
45
+ transform: scale(0.98);
46
+ transition-duration: var(--mw-duration-instant);
47
+ }
39
48
  }
40
49
 
41
50
  // Size variants
@@ -77,10 +86,7 @@ a.mw-info,
77
86
  button.mw-info {
78
87
  cursor: pointer;
79
88
 
80
- &:focus-visible {
81
- outline: 2px solid var(--mw-primary-text-color);
82
- outline-offset: 2px;
83
- }
89
+ @include focus-ring;
84
90
  }
85
91
 
86
92
  // Info like mini-buttons
@@ -92,7 +98,7 @@ button.mw-info {
92
98
  height: 20px;
93
99
  border-radius: radius('full');
94
100
  background: var(--mw-gray-color);
95
- color: #efefef;
101
+ color: $fixed-surface-text;
96
102
  border: none;
97
103
  padding: 0;
98
104
  line-height: 1;
@@ -18,6 +18,28 @@ $_mw-kanban-ribbon-clearance-compact: 58px;
18
18
  }
19
19
  }
20
20
 
21
+ // A card that has just been pushed to another lane arrives from the side it was
22
+ // pushed from, and takes visibly longer doing it than a new card takes to
23
+ // appear. The two are not the same event: a new card shows up exactly where the
24
+ // eye already is - the composer it was written in - while a moved one lands in a
25
+ // column somewhere else on the board, and has to be found there.
26
+ //
27
+ // Before this the move had no animation at all: the JS re-parented the card and
28
+ // it simply blinked into the other lane.
29
+ @keyframes mw-kanban-card-moved-forward {
30
+ from {
31
+ opacity: 0;
32
+ transform: translateX(-18px);
33
+ }
34
+ }
35
+
36
+ @keyframes mw-kanban-card-moved-back {
37
+ from {
38
+ opacity: 0;
39
+ transform: translateX(18px);
40
+ }
41
+ }
42
+
21
43
  // ---------------------------------------------------------------------------
22
44
  // Board
23
45
  // ---------------------------------------------------------------------------
@@ -129,7 +151,20 @@ $_mw-kanban-ribbon-clearance-compact: 58px;
129
151
  padding: spacing('4');
130
152
 
131
153
  &.mw-kanban-card-in {
132
- animation: mw-kanban-card-in 0.25s ease;
154
+ animation: mw-kanban-card-in var(--mw-duration-base) var(--mw-ease-out);
155
+ }
156
+
157
+ // `slow` rather than `base` - see the note by the keyframes. Retune the whole
158
+ // thing through --mw-duration-slow, or give these two rules a duration of
159
+ // their own if only the board should change.
160
+ &.mw-kanban-card-moved-forward {
161
+ animation: mw-kanban-card-moved-forward var(--mw-duration-slow)
162
+ var(--mw-ease-out);
163
+ }
164
+
165
+ &.mw-kanban-card-moved-back {
166
+ animation: mw-kanban-card-moved-back var(--mw-duration-slow)
167
+ var(--mw-ease-out);
133
168
  }
134
169
  }
135
170
 
@@ -225,10 +260,7 @@ $_mw-kanban-ribbon-clearance-compact: 58px;
225
260
  color: var(--mw-primary-accent-text-color);
226
261
  }
227
262
 
228
- &:focus-visible {
229
- outline: 2px solid var(--mw-primary-text-color);
230
- outline-offset: 2px;
231
- }
263
+ @include focus-ring;
232
264
 
233
265
  &:disabled {
234
266
  opacity: 0.35;
@@ -260,7 +292,7 @@ $_mw-kanban-ribbon-clearance-compact: 58px;
260
292
 
261
293
  &.mw-active {
262
294
  display: flex;
263
- animation: mw-kanban-card-in 0.2s ease;
295
+ animation: mw-kanban-card-in var(--mw-duration-fast) var(--mw-ease-out);
264
296
  }
265
297
 
266
298
  // Three lines of description without a scrollbar
@@ -358,6 +390,8 @@ $_mw-kanban-ribbon-clearance-compact: 58px;
358
390
 
359
391
  @media (prefers-reduced-motion: reduce) {
360
392
  .mw-kanban-card.mw-kanban-card-in,
393
+ .mw-kanban-card.mw-kanban-card-moved-forward,
394
+ .mw-kanban-card.mw-kanban-card-moved-back,
361
395
  .mw-kanban-composer.mw-active {
362
396
  animation: none;
363
397
  }
@@ -0,0 +1,43 @@
1
+ @use '../abstracts' as *;
2
+
3
+ // Keyboard key
4
+ kbd,
5
+ .mw-kbd {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ min-width: 1.6em;
10
+ padding: 0.15em 0.45em;
11
+ border: 1px solid var(--mw-border);
12
+ border-bottom-width: 3px;
13
+ border-radius: radius('xs');
14
+ background: var(--mw-surface-muted);
15
+ color: var(--mw-text-color);
16
+ font-family: var(--mw-font-family-mono);
17
+ font-size: 0.85em;
18
+ line-height: 1.4;
19
+ font-weight: font-weight('medium');
20
+ white-space: nowrap;
21
+ vertical-align: middle;
22
+ position: relative;
23
+ top: -1px;
24
+ }
25
+
26
+ // A combination - Ctrl + Shift + P - as one unit, so the pluses between the
27
+ // keys are spaced and do not wrap away from what they join
28
+ .mw-kbd-group {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ gap: spacing('1');
32
+ white-space: nowrap;
33
+ color: var(--mw-text-muted-color);
34
+ font-size: font-size('sm');
35
+ }
36
+
37
+ // A key shown mid-press, for a hint that demonstrates rather than lists
38
+ .mw-kbd-pressed {
39
+ border-bottom-width: 1px;
40
+ top: 1px;
41
+ background: var(--mw-primary-background);
42
+ border-color: var(--mw-primary-color);
43
+ }
@@ -110,8 +110,8 @@ $_checkbox-box-offset: 3px;
110
110
  transform: scaleX(1);
111
111
  transform-origin: left;
112
112
  transition:
113
- transform 0.2s ease,
114
- opacity 0.2s ease;
113
+ transform var(--mw-duration-fast) var(--mw-ease-out),
114
+ opacity var(--mw-duration-fast) var(--mw-ease-out);
115
115
  }
116
116
 
117
117
  &:hover {
@@ -177,8 +177,8 @@ $_checkbox-box-offset: 3px;
177
177
 
178
178
  // Smooth focus management for accessibility
179
179
  &:focus-within {
180
- outline: 2px solid var(--mw-primary-text-color);
181
- outline-offset: 2px;
180
+ outline: var(--mw-focus-ring-width) solid var(--mw-focus-ring-color);
181
+ outline-offset: var(--mw-focus-ring-offset);
182
182
  border-radius: radius('sm');
183
183
  }
184
184
  }
@@ -216,9 +216,9 @@ $_checkbox-box-offset: 3px;
216
216
  background: var(--mw-card-background);
217
217
  border: 1px solid transparent;
218
218
  transition:
219
- background 0.3s cubic-bezier(0.4, 0, 0.2, 1),
220
- border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
221
- transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
219
+ background var(--mw-duration-base) var(--mw-ease-out),
220
+ border-color var(--mw-duration-base) var(--mw-ease-out),
221
+ transform var(--mw-duration-base) var(--mw-ease-out);
222
222
  overflow: hidden;
223
223
 
224
224
  &::before {
@@ -229,7 +229,7 @@ $_checkbox-box-offset: 3px;
229
229
  bottom: 0;
230
230
  width: 0;
231
231
  background: var(--mw-primary-text-color);
232
- transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
232
+ transition: width var(--mw-duration-base) var(--mw-ease-out);
233
233
  }
234
234
 
235
235
  // The card carries its own background and radius, so moving the whole
@@ -238,12 +238,15 @@ $_checkbox-box-offset: 3px;
238
238
  &:hover {
239
239
  background: var(--mw-primary-background-hover);
240
240
  border-color: var(--mw-primary-text-color);
241
- transform: translateX(8px);
242
241
 
243
242
  &::before {
244
243
  width: 4px;
245
244
  }
246
245
  }
246
+
247
+ @include hover {
248
+ transform: translateX(8px);
249
+ }
247
250
  }
248
251
  }
249
252
 
@@ -274,8 +277,8 @@ $_checkbox-box-offset: 3px;
274
277
  padding: spacing('3');
275
278
  border-bottom: 1px solid var(--mw-border);
276
279
  transition:
277
- background 0.2s ease,
278
- padding-left 0.2s ease;
280
+ background var(--mw-duration-fast) var(--mw-ease-out),
281
+ padding-left var(--mw-duration-fast) var(--mw-ease-out);
279
282
  position: relative;
280
283
 
281
284
  // Always present at zero width so it can grow on hover - creating it
@@ -288,7 +291,7 @@ $_checkbox-box-offset: 3px;
288
291
  bottom: 0;
289
292
  width: 0;
290
293
  background: var(--mw-primary-text-color);
291
- transition: width 0.2s ease;
294
+ transition: width var(--mw-duration-fast) var(--mw-ease-out);
292
295
  }
293
296
 
294
297
  &:last-child {
@@ -349,16 +352,16 @@ $_checkbox-box-offset: 3px;
349
352
  border-radius: radius('lg');
350
353
  overflow: hidden;
351
354
  background: var(--mw-card-background);
352
- box-shadow: 0 2px 8px var(--mw-shadow);
355
+ box-shadow: var(--mw-elevation-2);
353
356
 
354
357
  > * {
355
358
  padding: spacing('4');
356
359
  border-bottom: 1px solid var(--mw-border);
357
360
  transition:
358
- background 0.2s cubic-bezier(0.4, 0, 0.2, 1),
359
- padding-left 0.2s cubic-bezier(0.4, 0, 0.2, 1),
360
- color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
361
- transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
361
+ background var(--mw-duration-fast) var(--mw-ease-out),
362
+ padding-left var(--mw-duration-fast) var(--mw-ease-out),
363
+ color var(--mw-duration-fast) var(--mw-ease-out),
364
+ transform var(--mw-duration-fast) var(--mw-ease-out);
362
365
  cursor: pointer;
363
366
  display: flex;
364
367
  align-items: center;
@@ -396,8 +399,8 @@ $_checkbox-box-offset: 3px;
396
399
  padding: spacing('3');
397
400
  border-bottom: 1px solid var(--mw-border);
398
401
  transition:
399
- background 0.2s ease,
400
- color 0.2s ease;
402
+ background var(--mw-duration-fast) var(--mw-ease-out),
403
+ color var(--mw-duration-fast) var(--mw-ease-out);
401
404
 
402
405
  &:last-child {
403
406
  border-bottom: none;
@@ -447,10 +450,10 @@ $_checkbox-box-offset: 3px;
447
450
  border-left: 3px solid transparent;
448
451
  cursor: pointer;
449
452
  transition:
450
- background 0.2s ease,
451
- color 0.2s ease,
452
- transform 0.2s ease,
453
- border-left-color 0.2s ease;
453
+ background var(--mw-duration-fast) var(--mw-ease-out),
454
+ color var(--mw-duration-fast) var(--mw-ease-out),
455
+ transform var(--mw-duration-fast) var(--mw-ease-out),
456
+ border-left-color var(--mw-duration-fast) var(--mw-ease-out);
454
457
  user-select: none;
455
458
 
456
459
  &:last-child {
@@ -8,14 +8,14 @@
8
8
  right: 0;
9
9
  bottom: 0;
10
10
  background: var(--mw-overlay-background);
11
- backdrop-filter: blur(2px);
11
+ backdrop-filter: blur(3px);
12
12
  z-index: z-index('modal')-10;
13
13
  display: none;
14
14
  align-items: center;
15
15
  justify-content: center;
16
16
  padding: spacing('7');
17
17
  opacity: 0;
18
- transition: opacity 0.4s ease;
18
+ transition: opacity var(--mw-duration-base) var(--mw-ease-out);
19
19
 
20
20
  // Show modal when class is added
21
21
  &.mw-modal-open {
@@ -28,13 +28,15 @@
28
28
  .mw-modal {
29
29
  background: var(--mw-card-background);
30
30
  border-radius: radius('sm') radius('xl') radius('sm') radius('xl');
31
- box-shadow: 0 25px 50px var(--mw-shadow);
31
+ box-shadow: var(--mw-elevation-5);
32
32
  max-width: 520px;
33
33
  width: 100%;
34
34
  max-height: 85dvh;
35
35
  display: flex;
36
36
  flex-direction: column;
37
37
  z-index: z-index('modal');
38
+ transform: scale(0.96) translateY(12px);
39
+ transition: transform var(--mw-duration-base) var(--mw-ease-out);
38
40
 
39
41
  .mw-modal-open & {
40
42
  transform: scale(1) translateY(0);
@@ -58,19 +60,66 @@
58
60
  }
59
61
  }
60
62
 
63
+ // Phone: the dialog becomes a sheet
61
64
  @include media-down('sm') {
62
65
  .mw-modal-overlay {
63
- padding: spacing('5');
66
+ padding: spacing('0');
67
+ align-items: flex-end;
68
+ }
69
+
70
+ .mw-modal,
71
+ .mw-modal.mw-modal-sm,
72
+ .mw-modal.mw-modal-lg,
73
+ .mw-modal.mw-modal-xl {
74
+ max-width: 100%;
75
+ max-height: 92dvh;
76
+ border-radius: radius('xl') radius('xl') radius('none') radius('none');
77
+ padding-bottom: env(safe-area-inset-bottom, 0px);
78
+ // Straight up from the bottom edge - a sheet does not scale in
79
+ transform: translateY(100%);
80
+ transition: transform var(--mw-duration-slow) var(--mw-ease-out);
81
+ }
82
+
83
+ .mw-modal-open .mw-modal {
84
+ transform: translateY(0);
85
+ }
86
+
87
+ // The grab handle. It does nothing - there is no drag-to-dismiss behind it -
88
+ // but it is the mark that says "this came up from the bottom and goes back
89
+ // down", and a sheet without one reads as a page that got stuck.
90
+ .mw-modal-header::before {
91
+ content: '';
92
+ position: absolute;
93
+ top: spacing('2');
94
+ left: 50%;
95
+ transform: translateX(-50%);
96
+ width: 36px;
97
+ height: 4px;
98
+ border-radius: radius('lg');
99
+ background: var(--mw-text-muted-color);
100
+ opacity: 0.45;
101
+ }
102
+
103
+ .mw-modal-header {
104
+ position: relative;
105
+ padding: spacing('6') spacing('4') spacing('3');
64
106
  }
65
107
 
66
- .mw-modal-header,
67
108
  .mw-modal-footer {
68
- padding: spacing('3') spacing('4');
109
+ padding: spacing('4');
69
110
  }
70
111
 
71
112
  .mw-modal-body {
72
113
  padding: spacing('4');
73
114
  }
115
+
116
+ // On a phone the actions are the reason the sheet is open. Full width, in
117
+ // reading order, thumb-sized - not two 80px buttons huddled in a corner.
118
+ .mw-modal-footer .mw-btn {
119
+ flex: 1 1 auto;
120
+ min-width: 0;
121
+ min-height: 2.75rem;
122
+ }
74
123
  }
75
124
 
76
125
  // Modal sections
@@ -101,6 +150,8 @@
101
150
  padding: spacing('4') spacing('5');
102
151
  overflow-y: auto;
103
152
  flex: 1;
153
+ overscroll-behavior: contain;
154
+ @include scrollbar;
104
155
  }
105
156
 
106
157
  .mw-modal-footer {
@@ -126,11 +177,25 @@
126
177
  align-items: center;
127
178
  justify-content: center;
128
179
  color: var(--mw-text-color);
180
+ transition: var(--mw-transition-fast);
181
+ @include focus-ring;
182
+ @include tappable;
129
183
 
130
184
  &:hover {
131
185
  background: var(--mw-primary-color-hover);
132
186
  color: var(--mw-primary-accent-text-color);
133
187
  }
188
+
189
+ &:active {
190
+ transform: scale(0.92);
191
+ transition-duration: var(--mw-duration-instant);
192
+ }
193
+
194
+ // The one control on the sheet a thumb has to find without looking
195
+ @include media-down('sm') {
196
+ min-width: 2.75rem;
197
+ min-height: 2.75rem;
198
+ }
134
199
  }
135
200
 
136
201
  // Backdrop for click-outside-to-close.
@@ -8,7 +8,7 @@
8
8
  background: var(--mw-card-background);
9
9
  border: 1px solid var(--mw-border);
10
10
  border-radius: radius('sm') radius('xl') radius('sm') radius('xl');
11
- box-shadow: 0 5px 10px var(--mw-shadow);
11
+ box-shadow: var(--mw-elevation-2);
12
12
  }
13
13
 
14
14
  // The calendar gets its separation from the weekday row - here there is
@@ -57,11 +57,12 @@
57
57
 
58
58
  // Optional directional transitions for the swap
59
59
  .mw-pagination-slide-left {
60
- animation: mw-pagination-slide-left 0.3s ease;
60
+ animation: mw-pagination-slide-left var(--mw-duration-base) var(--mw-ease-out);
61
61
  }
62
62
 
63
63
  .mw-pagination-slide-right {
64
- animation: mw-pagination-slide-right 0.3s ease;
64
+ animation: mw-pagination-slide-right var(--mw-duration-base)
65
+ var(--mw-ease-out);
65
66
  }
66
67
 
67
68
  @keyframes mw-pagination-slide-left {
@@ -17,27 +17,26 @@
17
17
  justify-content: space-between;
18
18
  align-items: center;
19
19
  margin: spacing('0');
20
+ border-radius: (radius('sm') - 2px) (radius('xl') - 2px) 0 0;
20
21
  }
21
22
 
22
23
  &-body {
23
24
  padding: spacing('4') spacing('5');
24
25
  flex: 1;
25
26
  overflow-y: auto;
27
+ @include scrollbar;
28
+ }
26
29
 
27
- // Scrollbar styling
28
- &::-webkit-scrollbar {
29
- width: 6px;
30
- }
31
-
32
- &::-webkit-scrollbar-track {
33
- background: var(--mw-card-background);
34
- border-radius: radius('sm');
35
- }
36
-
37
- &::-webkit-scrollbar-thumb {
38
- background: var(--mw-primary-color-hover);
39
- border-radius: radius('sm');
40
- }
30
+ // A dropdown, a tooltip, a date picker - anything a child opens *outside*
31
+ // itself - is cut off by the two clips above. Lifting them only while such a
32
+ // menu is open costs nothing the rest of the time, and the alternative is a
33
+ // menu that shows its first row and nothing else.
34
+ //
35
+ // This is the same escape hatch a project needs on its own containers: one
36
+ // `:has(.mw-dropdown[open]) { overflow: visible }` on whatever is clipping.
37
+ &:has(.mw-dropdown[open]),
38
+ &-body:has(.mw-dropdown[open]) {
39
+ overflow: visible;
41
40
  }
42
41
 
43
42
  &-footer {
@@ -74,7 +74,7 @@ $_mw-progress-colors: (
74
74
  background: var(--mw-secondary-color);
75
75
  border-radius: radius('sm');
76
76
  width: 0;
77
- transition: width 1.9s ease-in-out;
77
+ transition: width var(--mw-duration-slower) var(--mw-ease-in-out);
78
78
  }
79
79
 
80
80
  // Sizes
@@ -45,12 +45,16 @@
45
45
  color: var(--mw-text-color);
46
46
  }
47
47
 
48
- // Inset, because an outline outside the item would be clipped by the frame
49
- &:focus-visible {
50
- outline: 2px solid var(--mw-primary-text-color);
51
- outline-offset: -2px;
48
+ @include tappable;
49
+
50
+ &:active {
51
+ transform: scale(0.97);
52
+ transition-duration: var(--mw-duration-instant);
52
53
  }
53
54
 
55
+ // Inset, because an outline outside the item would be clipped by the frame
56
+ @include focus-ring-inset;
57
+
54
58
  &:disabled {
55
59
  cursor: not-allowed;
56
60
  opacity: 0.6;
@@ -22,7 +22,7 @@
22
22
  height: 2px;
23
23
  background: var(--mw-border);
24
24
  margin-top: spacing('4');
25
- transition: background 0.3s ease;
25
+ transition: background var(--mw-duration-base) var(--mw-ease-out);
26
26
 
27
27
  &.mw-done {
28
28
  background: var(--mw-primary-color);
@@ -65,7 +65,7 @@
65
65
  color: var(--mw-text-muted-color);
66
66
  text-align: center;
67
67
  line-height: 1.2;
68
- transition: color 0.3s ease;
68
+ transition: color var(--mw-duration-base) var(--mw-ease-out);
69
69
 
70
70
  &.mw-active {
71
71
  color: var(--mw-primary-text-color);
@@ -110,7 +110,7 @@
110
110
  bottom: 0;
111
111
  width: 2px;
112
112
  background: var(--mw-border);
113
- transition: background 0.3s ease;
113
+ transition: background var(--mw-duration-base) var(--mw-ease-out);
114
114
  }
115
115
 
116
116
  &.mw-done:not(:last-child)::after {
@@ -2,14 +2,14 @@
2
2
 
3
3
  // Base table styles
4
4
  .mw-table {
5
- width: 98%;
6
- margin: spacing('1');
5
+ width: 100%;
6
+ margin: spacing('1') spacing('0');
7
7
  border-collapse: collapse;
8
8
  background: var(--mw-card-background);
9
9
 
10
10
  th,
11
11
  td {
12
- padding: spacing('2');
12
+ padding: spacing('3') spacing('4');
13
13
  text-align: left;
14
14
  border: 1px solid var(--mw-border);
15
15
  color: var(--mw-text-muted-color);
@@ -35,12 +35,9 @@
35
35
  }
36
36
 
37
37
  @include media-down('sm') {
38
- width: 100%;
39
- margin-inline: spacing('0');
40
-
41
38
  th,
42
39
  td {
43
- padding: spacing('1') spacing('2');
40
+ padding: spacing('2') spacing('3');
44
41
  font-size: font-size('xs');
45
42
  }
46
43
  }
@@ -87,7 +84,7 @@
87
84
  tr {
88
85
  display: block;
89
86
  margin-bottom: spacing('3');
90
- box-shadow: 0 5px 7px var(--mw-shadow);
87
+ box-shadow: var(--mw-elevation-2);
91
88
  background: var(--mw-card-background);
92
89
  cursor: text;
93
90
  }
@@ -25,19 +25,36 @@
25
25
  }
26
26
  }
27
27
 
28
+ // Written for a <button>. A tab is the primary navigation of the view it
29
+ // sits in, and as a <div> it is not focusable, not reachable by keyboard and
30
+ // announces nothing - the one control on the page a keyboard user cannot get
31
+ // to. The declarations below clear what comes with a <button>; on a <div>
32
+ // they change nothing, so old markup keeps working.
28
33
  &-nav-item {
34
+ appearance: none;
35
+ background: none;
36
+ border: none;
37
+ font: inherit;
29
38
  padding: spacing('3') spacing('4');
30
39
  cursor: pointer;
31
40
  font-weight: font-weight('medium');
32
41
  color: var(--mw-text-muted-color);
33
42
  border-bottom: 2px solid transparent;
34
- transition: all 0.3s ease;
43
+ transition: var(--mw-transition);
35
44
  white-space: nowrap;
45
+ @include tappable;
46
+ // Inset: a ring outside the item is clipped by the strip's own scroll
47
+ @include focus-ring-inset;
36
48
 
37
49
  &:hover {
38
50
  color: var(--mw-primary-text-color);
39
51
  }
40
52
 
53
+ &:active {
54
+ color: var(--mw-primary-text-color);
55
+ transition-duration: var(--mw-duration-instant);
56
+ }
57
+
41
58
  &.mw-active,
42
59
  &.active {
43
60
  color: var(--mw-primary-text-color);
@@ -56,7 +73,9 @@
56
73
  &.mw-active,
57
74
  &.active {
58
75
  display: block;
59
- animation: fadeIn 1.1s ease;
76
+ // 1.1s to reveal a tab panel means a second of blank space after every
77
+ // click. A panel switch is a state change, not an entrance.
78
+ animation: fadeIn var(--mw-duration-base) var(--mw-ease-out);
60
79
  }
61
80
  }
62
81
 
@@ -139,7 +158,7 @@
139
158
  .mw-tabs-nav-item {
140
159
  border-radius: radius('xl');
141
160
  padding: spacing('4') spacing('5');
142
- line-height: 0.9;
161
+ line-height: 1.2;
143
162
  border: 1px solid var(--mw-border-accent);
144
163
  background: var(--mw-card-background);
145
164