maverick-wave 4.27.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.
Files changed (140) hide show
  1. package/.claude/settings.local.json +29 -1
  2. package/.claude/skills/mw-maverick-wave/SKILL.md +42 -25
  3. package/.claude/skills/mw-maverick-wave/examples/angular-services.md +16 -4
  4. package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +13 -4
  5. package/.claude/skills/mw-maverick-wave/references/components.md +90 -5
  6. package/.claude/skills/mw-maverick-wave/references/forms.md +14 -2
  7. package/.claude/skills/mw-maverick-wave/references/javascript.md +18 -4
  8. package/.claude/skills/mw-maverick-wave/references/layout.md +53 -19
  9. package/.claude/skills/mw-maverick-wave/references/theming.md +38 -1
  10. package/.impeccable/config.local.json +5 -0
  11. package/.impeccable/hook.cache.json +1 -0
  12. package/CHANGELOG.md +17 -0
  13. package/CLAUDE.md +5 -5
  14. package/README.md +48 -4
  15. package/index.html +19 -38
  16. package/maverick-wave.min.css +14 -12
  17. package/maverick-wave.min.js +1 -1
  18. package/package.json +2 -2
  19. package/scripts/verify.js +27 -2
  20. package/src/js/main.js +266 -75
  21. package/src/partials/accordions-container.html +6 -10
  22. package/src/partials/alerts-container.html +6 -6
  23. package/src/partials/announcement-container.html +5 -5
  24. package/src/partials/avatars-container.html +85 -17
  25. package/src/partials/badges-container.html +6 -6
  26. package/src/partials/blog-posts-container.html +11 -12
  27. package/src/partials/buttons-container.html +3 -3
  28. package/src/partials/cards-container.html +26 -9
  29. package/src/partials/code-container.html +5 -5
  30. package/src/partials/content-slider-container.html +5 -4
  31. package/src/partials/divider-container.html +7 -7
  32. package/src/partials/dropdown-container.html +2 -2
  33. package/src/partials/empty-state-container.html +5 -5
  34. package/src/partials/footer-container.html +21 -18
  35. package/src/partials/form-elements-container.html +14 -14
  36. package/src/partials/gallery-container.html +16 -8
  37. package/src/partials/get-started-container.html +4 -8
  38. package/src/partials/header-container.html +18 -7
  39. package/src/partials/header-utilities-container.html +192 -5
  40. package/src/partials/home-container.html +10 -20
  41. package/src/partials/input-group-container.html +11 -2
  42. package/src/partials/kbd-container.html +1 -1
  43. package/src/partials/login-container.html +5 -1
  44. package/src/partials/media-container.html +2 -2
  45. package/src/partials/modals-container.html +22 -32
  46. package/src/partials/pricing-container.html +9 -9
  47. package/src/partials/skeleton-container.html +6 -6
  48. package/src/partials/stepper-container.html +2 -2
  49. package/src/partials/tables-container.html +12 -12
  50. package/src/partials/tabs-container.html +17 -27
  51. package/src/partials/tags-container.html +23 -17
  52. package/src/partials/techstack-bucket-container.html +13 -0
  53. package/src/partials/tiles-container.html +26 -9
  54. package/src/partials/typography-container.html +7 -6
  55. package/src/partials/utilities-container.html +35 -15
  56. package/src/scss/_layers.scss +10 -0
  57. package/src/scss/abstracts/_index.scss +6 -0
  58. package/src/scss/abstracts/_mixins.scss +61 -153
  59. package/src/scss/abstracts/_variables.scss +123 -319
  60. package/src/scss/base/_base.scss +170 -190
  61. package/src/scss/base/_reset.scss +106 -104
  62. package/src/scss/base/_typography.scss +153 -151
  63. package/src/scss/components/_accordions.scss +97 -97
  64. package/src/scss/components/_alerts.scss +71 -70
  65. package/src/scss/components/_announcement.scss +71 -70
  66. package/src/scss/components/_avatars.scss +130 -142
  67. package/src/scss/components/_badge.scss +131 -132
  68. package/src/scss/components/_blog-post.scss +223 -220
  69. package/src/scss/components/_breadcrumbs.scss +93 -92
  70. package/src/scss/components/_button-bar.scss +102 -110
  71. package/src/scss/components/_buttons.scss +319 -324
  72. package/src/scss/components/_calendar.scss +251 -252
  73. package/src/scss/components/_cards.scss +359 -386
  74. package/src/scss/components/_code.scss +190 -194
  75. package/src/scss/components/_coming-soon.scss +77 -75
  76. package/src/scss/components/_content-slider.scss +90 -89
  77. package/src/scss/components/_divider.scss +55 -53
  78. package/src/scss/components/_dropdown.scss +179 -185
  79. package/src/scss/components/_empty-state.scss +57 -57
  80. package/src/scss/components/_flag.scss +325 -0
  81. package/src/scss/components/_gallery.scss +131 -133
  82. package/src/scss/components/_index.scss +2 -0
  83. package/src/scss/components/_info.scss +151 -167
  84. package/src/scss/components/_kanban.scss +332 -341
  85. package/src/scss/components/_kbd.scss +40 -38
  86. package/src/scss/components/_lang-switch.scss +108 -0
  87. package/src/scss/components/_links.scss +21 -28
  88. package/src/scss/components/_lists.scss +510 -514
  89. package/src/scss/components/_localhost-indicator.scss +26 -24
  90. package/src/scss/components/_media.scss +22 -20
  91. package/src/scss/components/_meta-info.scss +35 -33
  92. package/src/scss/components/_modals.scss +277 -186
  93. package/src/scss/components/_pagination.scss +81 -87
  94. package/src/scss/components/_panels.scss +99 -97
  95. package/src/scss/components/_pricing.scss +183 -241
  96. package/src/scss/components/_progress.scss +112 -89
  97. package/src/scss/components/_prose.scss +35 -33
  98. package/src/scss/components/_ratings.scss +40 -38
  99. package/src/scss/components/_segmented.scss +82 -84
  100. package/src/scss/components/_skeleton.scss +66 -72
  101. package/src/scss/components/_spinners.scss +155 -159
  102. package/src/scss/components/_stepper.scss +116 -116
  103. package/src/scss/components/_tables.scss +155 -148
  104. package/src/scss/components/_tabs.scss +232 -141
  105. package/src/scss/components/_tags.scss +109 -107
  106. package/src/scss/components/_techstack-bucket.scss +123 -122
  107. package/src/scss/components/_testimonial.scss +72 -70
  108. package/src/scss/components/_theme-toggle.scss +53 -51
  109. package/src/scss/components/_tiles.scss +174 -174
  110. package/src/scss/components/_timelines.scss +282 -280
  111. package/src/scss/components/_toasts.scss +66 -72
  112. package/src/scss/form-elements/_checkbox.scss +117 -132
  113. package/src/scss/form-elements/_form.scss +149 -115
  114. package/src/scss/form-elements/_input-group.scss +99 -103
  115. package/src/scss/form-elements/_input.scss +74 -74
  116. package/src/scss/form-elements/_login.scss +48 -48
  117. package/src/scss/form-elements/_prefilled.scss +53 -51
  118. package/src/scss/form-elements/_radio.scss +95 -107
  119. package/src/scss/form-elements/_select.scss +42 -42
  120. package/src/scss/form-elements/_slider.scss +117 -132
  121. package/src/scss/form-elements/_textarea.scss +68 -54
  122. package/src/scss/form-elements/_toggle.scss +127 -140
  123. package/src/scss/layout/_footer.scss +172 -171
  124. package/src/scss/layout/_grid.scss +268 -302
  125. package/src/scss/layout/_header.scss +426 -427
  126. package/src/scss/layout/_home.scss +28 -27
  127. package/src/scss/layout/_main.scss +275 -238
  128. package/src/scss/layout/_page-header.scss +38 -36
  129. package/src/scss/layout/_section.scss +150 -124
  130. package/src/scss/main.scss +1 -1
  131. package/src/scss/utilities/_accessibility.scss +46 -45
  132. package/src/scss/utilities/_aspect.scss +22 -20
  133. package/src/scss/utilities/_corner.scss +23 -5
  134. package/src/scss/utilities/_display.scss +76 -70
  135. package/src/scss/utilities/_elevation.scss +13 -11
  136. package/src/scss/utilities/_flex.scss +83 -85
  137. package/src/scss/utilities/_reveal.scss +40 -63
  138. package/src/scss/utilities/_spacing.scss +63 -64
  139. package/src/scss/utilities/_text.scss +139 -141
  140. package/src/scss/utilities/_touch-targets.scss +130 -147
@@ -1,670 +1,666 @@
1
1
  @use '../abstracts' as *;
2
2
 
3
- // One scrollbar look for every scrollable list. Was copy-pasted per variant
4
- // before, which is how the checkbox list ended up with track and thumb in the
5
- // same color - an invisible scrollbar.
6
- @mixin _list-scrollbar {
7
- scrollbar-gutter: stable; // Prevent layout shift
8
-
9
- &::-webkit-scrollbar {
10
- width: 7px;
11
- }
12
-
13
- &::-webkit-scrollbar-track {
14
- background: var(--mw-primary-background);
15
- border-radius: 3px;
16
- }
3
+ @layer mw.components {
4
+ // One scrollbar look for every scrollable list. Was copy-pasted per variant
5
+ // before, which is how the checkbox list ended up with track and thumb in the
6
+ // same color - an invisible scrollbar.
7
+ @mixin _list-scrollbar {
8
+ scrollbar-gutter: stable; // Prevent layout shift
17
9
 
18
- &::-webkit-scrollbar-thumb {
19
- background: var(--mw-text-muted-color);
20
- border-radius: 3px;
10
+ &::-webkit-scrollbar {
11
+ width: 7px;
12
+ }
21
13
 
22
- &:hover {
23
- background: var(--mw-primary-color);
14
+ &::-webkit-scrollbar-track {
15
+ background: var(--mw-primary-background);
16
+ border-radius: 3px;
24
17
  }
25
- }
26
18
 
27
- // Modern Firefox scrollbar - needs both thumb and track, a single value
28
- // makes the whole declaration invalid
29
- scrollbar-width: thin;
30
- scrollbar-color: var(--mw-text-muted-color) var(--mw-gray-background);
31
- }
19
+ &::-webkit-scrollbar-thumb {
20
+ background: var(--mw-text-muted-color);
21
+ border-radius: 3px;
32
22
 
33
- // Checkbox box and checkmark sizes - shape-drawing values, so px instead of
34
- // spacing() keys. The checkmark has to scale with the box: compact used to be
35
- // an 8px box (4px of usable space inside the 2px border) holding a 5.6px
36
- // checkmark, so the mark broke out of its own box.
37
- $_checkbox-box-compact: 12px;
38
- $_checkbox-box-default: 14px;
39
- $_checkbox-box-large: 16px;
40
- $_check-compact-w: 5px;
41
- $_check-compact-h: 3px;
42
- $_check-default-w: 6px;
43
- $_check-default-h: 3px;
44
- $_check-large-w: 7px;
45
- $_check-large-h: 4px;
46
- // Nudges the box down onto the first text line when a header is present
47
- $_checkbox-box-offset: 3px;
48
-
49
- // Base list styles
50
- .mw-list {
51
- margin: spacing('4') spacing('0');
52
- padding: spacing('0') spacing('2');
53
-
54
- li {
55
- margin-bottom: spacing('1');
56
-
57
- &:last-child {
58
- margin-bottom: spacing('0');
23
+ &:hover {
24
+ background: var(--mw-primary-color);
25
+ }
59
26
  }
60
- }
61
27
 
62
- // Nested lists
63
- .mw-list {
64
- margin: spacing('1');
28
+ // Modern Firefox scrollbar - needs both thumb and track, a single value
29
+ // makes the whole declaration invalid
30
+ scrollbar-width: thin;
31
+ scrollbar-color: var(--mw-text-muted-color) var(--mw-gray-background);
65
32
  }
66
- }
67
33
 
68
- // Unstyled list - removes bullets and padding
69
- .mw-list-unstyled {
70
- list-style: none;
71
- padding-left: spacing('1');
72
- }
34
+ // Checkbox box and checkmark sizes - shape-drawing values, so px instead of
35
+ // spacing() keys. The checkmark has to scale with the box: compact used to be
36
+ // an 8px box (4px of usable space inside the 2px border) holding a 5.6px
37
+ // checkmark, so the mark broke out of its own box.
38
+ $_checkbox-box-compact: 12px;
39
+ $_checkbox-box-default: 14px;
40
+ $_checkbox-box-large: 16px;
41
+ $_check-compact-w: 5px;
42
+ $_check-compact-h: 3px;
43
+ $_check-default-w: 6px;
44
+ $_check-default-h: 3px;
45
+ $_check-large-w: 7px;
46
+ $_check-large-h: 4px;
47
+ // Nudges the box down onto the first text line when a header is present
48
+ $_checkbox-box-offset: 3px;
73
49
 
74
- // Inline list - horizontal layout
75
- .mw-list-inline {
76
- list-style: none;
77
- padding-left: spacing('1');
50
+ .mw-list {
51
+ margin: spacing('4') spacing('0');
52
+ padding: spacing('0') spacing('2');
78
53
 
79
- li {
80
- display: inline-block;
81
- margin-right: spacing('4');
54
+ li {
55
+ margin-bottom: spacing('1');
82
56
 
83
- &:last-child {
84
- margin-right: spacing('0');
85
- }
86
- }
87
- }
88
-
89
- // Link list - with anchor tag
90
- .mw-list-link {
91
- list-style: none;
92
-
93
- a {
94
- display: inline-block;
95
- position: relative;
96
- color: var(--mw-text-muted-color);
97
- text-decoration: none;
98
- padding-bottom: 2px;
99
-
100
- // subtle default underline via box‐shadow
101
- &::after {
102
- content: '';
103
- position: absolute;
104
- left: 0;
105
- bottom: 1px;
106
- width: 100%;
107
- height: 1px;
108
- background: currentColor;
109
- opacity: 0.4;
110
- transform: scaleX(1);
111
- transform-origin: left;
112
- transition:
113
- transform var(--mw-duration-fast) var(--mw-ease-out),
114
- opacity var(--mw-duration-fast) var(--mw-ease-out);
57
+ &:last-child {
58
+ margin-bottom: spacing('0');
59
+ }
115
60
  }
116
61
 
117
- &:hover {
118
- color: var(--mw-primary-text-color);
119
-
120
- &::after {
121
- opacity: 1;
122
- height: 2px;
123
- transform: scaleX(1.1);
124
- }
62
+ .mw-list {
63
+ margin: spacing('1');
125
64
  }
126
65
  }
127
- }
128
66
 
129
- // Dot lists
130
- .mw-list-dot {
131
- // outside keeps a wrapping line flush with the text instead of letting it
132
- // run back underneath the bullet - the padding makes room for the marker
133
- padding-left: spacing('6');
134
- list-style: disc outside;
135
-
136
- li {
67
+ .mw-list-unstyled {
68
+ list-style: none;
137
69
  padding-left: spacing('1');
138
- margin-bottom: spacing('1');
139
-
140
- // ::marker only takes color, content and font properties - positioning
141
- // it has no effect
142
- &::marker {
143
- color: var(--mw-primary-text-color);
144
- }
145
70
  }
146
- }
147
71
 
148
- // Check list
149
- .mw-list-check {
150
- list-style: none;
151
- padding-left: spacing('3');
72
+ .mw-list-inline {
73
+ list-style: none;
74
+ padding-left: spacing('1');
152
75
 
153
- li {
154
- position: relative;
155
- padding-left: spacing('6');
156
- margin-bottom: spacing('1');
157
-
158
- // Taken out of the flow so a wrapping line keeps its indent instead of
159
- // running back underneath the checkmark
160
- &::before {
161
- content: '✓';
162
- position: absolute;
163
- left: 0;
164
- color: var(--mw-primary-text-color);
76
+ li {
77
+ display: inline-block;
78
+ margin-right: spacing('4');
79
+
80
+ &:last-child {
81
+ margin-right: spacing('0');
82
+ }
165
83
  }
166
84
  }
167
- }
168
85
 
169
- // Base item list - flexible container for any content
170
- .mw-item-list {
171
- display: flex;
172
- flex-direction: column;
173
- gap: spacing('3');
174
- padding: 0;
175
- margin: 0;
176
- list-style: none;
177
-
178
- // Smooth focus management for accessibility
179
- &:focus-within {
180
- outline: var(--mw-focus-ring-width) solid var(--mw-focus-ring-color);
181
- outline-offset: var(--mw-focus-ring-offset);
182
- border-radius: radius('sm');
183
- }
184
- }
86
+ .mw-list-link {
87
+ list-style: none;
185
88
 
186
- // Horizontal item list
187
- .mw-item-list-horizontal {
188
- @extend .mw-item-list;
189
- flex-direction: row;
190
- flex-wrap: wrap;
191
- align-items: flex-start;
89
+ a {
90
+ display: inline-block;
91
+ position: relative;
92
+ color: var(--mw-text-muted-color);
93
+ text-decoration: none;
94
+ padding-bottom: 2px;
192
95
 
193
- @include media-down('sm') {
194
- flex-direction: column;
195
- }
196
- }
96
+ // subtle default underline via box‐shadow
97
+ &::after {
98
+ content: '';
99
+ position: absolute;
100
+ left: 0;
101
+ bottom: 1px;
102
+ width: 100%;
103
+ height: 1px;
104
+ background: currentColor;
105
+ opacity: 0.4;
106
+ transform: scaleX(1);
107
+ transform-origin: left;
108
+ transition:
109
+ transform var(--mw-duration-fast) var(--mw-ease-out),
110
+ opacity var(--mw-duration-fast) var(--mw-ease-out);
111
+ }
197
112
 
198
- // Interactive card list
199
- .mw-item-list-cards {
200
- @extend .mw-item-list;
201
- gap: spacing('4');
113
+ &:hover {
114
+ color: var(--mw-primary-text-color);
202
115
 
203
- > * {
204
- position: relative;
116
+ &::after {
117
+ opacity: 1;
118
+ height: 2px;
119
+ transform: scaleX(1.1);
120
+ }
121
+ }
122
+ }
205
123
  }
206
- }
207
124
 
208
- // Sliding border list
209
- .mw-item-list-slide {
210
- @extend .mw-item-list;
125
+ .mw-list-dot {
126
+ // outside keeps a wrapping line flush with the text instead of letting it
127
+ // run back underneath the bullet - the padding makes room for the marker
128
+ padding-left: spacing('6');
129
+ list-style: disc outside;
211
130
 
212
- > * {
213
- position: relative;
214
- border-radius: radius('sm');
215
- padding: spacing('3');
216
- background: var(--mw-card-background);
217
- border: 1px solid transparent;
218
- transition:
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
- overflow: hidden;
131
+ li {
132
+ padding-left: spacing('1');
133
+ margin-bottom: spacing('1');
223
134
 
224
- &::before {
225
- content: '';
226
- position: absolute;
227
- left: 0;
228
- top: 0;
229
- bottom: 0;
230
- width: 0;
231
- background: var(--mw-primary-text-color);
232
- transition: width var(--mw-duration-base) var(--mw-ease-out);
135
+ // ::marker only takes color, content and font properties - positioning
136
+ // it has no effect
137
+ &::marker {
138
+ color: var(--mw-primary-text-color);
139
+ }
233
140
  }
141
+ }
142
+
143
+ // Check list
144
+ .mw-list-check {
145
+ list-style: none;
146
+ padding-left: spacing('3');
234
147
 
235
- // The card carries its own background and radius, so moving the whole
236
- // thing reads the same as growing the padding did - and runs on the
237
- // compositor instead of relaying out the item on every hover
238
- &:hover {
239
- background: var(--mw-primary-background-hover);
240
- border-color: var(--mw-primary-text-color);
148
+ li {
149
+ position: relative;
150
+ padding-left: spacing('6');
151
+ margin-bottom: spacing('1');
241
152
 
153
+ // Taken out of the flow so a wrapping line keeps its indent instead of
154
+ // running back underneath the checkmark
242
155
  &::before {
243
- width: 4px;
156
+ content: '✓';
157
+ position: absolute;
158
+ left: 0;
159
+ color: var(--mw-primary-text-color);
244
160
  }
245
161
  }
162
+ }
246
163
 
247
- @include hover {
248
- transform: translateX(8px);
164
+ // Base item list - flexible container for any content
165
+ .mw-item-list {
166
+ display: flex;
167
+ flex-direction: column;
168
+ gap: spacing('3');
169
+ padding: 0;
170
+ margin: 0;
171
+ list-style: none;
172
+
173
+ // Smooth focus management for accessibility
174
+ &:focus-within {
175
+ outline: var(--mw-focus-ring-width) solid var(--mw-focus-ring-color);
176
+ outline-offset: var(--mw-focus-ring-offset);
177
+ border-radius: radius('sm');
249
178
  }
250
179
  }
251
- }
252
180
 
253
- // Secondary variant - additive, sits alongside mw-item-list-slide
254
- .mw-item-list-slide-secondary {
255
- > * {
256
- &::before {
257
- background: var(--mw-secondary-text-color);
258
- }
181
+ // Horizontal item list
182
+ .mw-item-list-horizontal {
183
+ @extend .mw-item-list;
184
+ flex-direction: column;
185
+ flex-wrap: wrap;
186
+ align-items: flex-start;
259
187
 
260
- &:hover {
261
- background: var(--mw-secondary-background-hover);
262
- border-color: var(--mw-secondary-text-color);
188
+ @include media-up('sm') {
189
+ flex-direction: row;
263
190
  }
264
191
  }
265
- }
266
192
 
267
- // Compact item list
268
- .mw-item-list-compact {
269
- @extend .mw-item-list;
270
- gap: 0;
271
- border: 1px solid var(--mw-border);
272
- border-radius: radius('md');
273
- overflow: hidden;
274
- background: var(--mw-card-background);
275
-
276
- > * {
277
- padding: spacing('3');
278
- border-bottom: 1px solid var(--mw-border);
279
- transition:
280
- background var(--mw-duration-fast) var(--mw-ease-out),
281
- padding-left var(--mw-duration-fast) var(--mw-ease-out);
282
- position: relative;
283
-
284
- // Always present at zero width so it can grow on hover - creating it
285
- // inside :hover means it snaps in with no transition
286
- &::before {
287
- content: '';
288
- position: absolute;
289
- left: 0;
290
- top: 0;
291
- bottom: 0;
292
- width: 0;
293
- background: var(--mw-primary-text-color);
294
- transition: width var(--mw-duration-fast) var(--mw-ease-out);
295
- }
193
+ // Interactive card list
194
+ .mw-item-list-cards {
195
+ @extend .mw-item-list;
196
+ gap: spacing('4');
296
197
 
297
- &:last-child {
298
- border-bottom: none;
198
+ > * {
199
+ position: relative;
299
200
  }
201
+ }
300
202
 
301
- &:hover {
302
- background: var(--mw-primary-background-hover);
303
- padding-left: spacing('4');
203
+ // Sliding border list
204
+ .mw-item-list-slide {
205
+ @extend .mw-item-list;
206
+
207
+ > * {
208
+ position: relative;
209
+ border-radius: radius('sm');
210
+ padding: spacing('3');
211
+ background: var(--mw-card-background);
212
+ border: 1px solid transparent;
213
+ transition:
214
+ background var(--mw-duration-base) var(--mw-ease-out),
215
+ border-color var(--mw-duration-base) var(--mw-ease-out),
216
+ transform var(--mw-duration-base) var(--mw-ease-out);
217
+ overflow: hidden;
304
218
 
305
219
  &::before {
306
- width: 3px;
220
+ content: '';
221
+ position: absolute;
222
+ left: 0;
223
+ top: 0;
224
+ bottom: 0;
225
+ width: 0;
226
+ background: var(--mw-primary-text-color);
227
+ transition: width var(--mw-duration-base) var(--mw-ease-out);
307
228
  }
308
- }
309
-
310
- // Handle nested compact lists
311
- &:has(.mw-item-list-compact) {
312
- padding-bottom: spacing('1');
313
229
 
230
+ // The card carries its own background and radius, so moving the whole
231
+ // thing reads the same as growing the padding did - and runs on the
232
+ // compositor instead of relaying out the item on every hover
314
233
  &:hover {
315
- padding-left: spacing('4');
234
+ background: var(--mw-primary-background-hover);
235
+ border-color: var(--mw-primary-text-color);
316
236
 
317
237
  &::before {
318
- width: 0;
238
+ width: 4px;
319
239
  }
320
240
  }
241
+
242
+ @include hover {
243
+ transform: translateX(8px);
244
+ }
321
245
  }
322
246
  }
323
247
 
324
- // Nested compact lists styling - only the left rule, the full border comes
325
- // from the outer rule and would frame the nested list a second time
248
+ // Secondary variant - additive, sits alongside mw-item-list-slide
249
+ .mw-item-list-slide-secondary {
250
+ > * {
251
+ &::before {
252
+ background: var(--mw-secondary-text-color);
253
+ }
254
+
255
+ &:hover {
256
+ background: var(--mw-secondary-background-hover);
257
+ border-color: var(--mw-secondary-text-color);
258
+ }
259
+ }
260
+ }
261
+
262
+ // Compact item list
326
263
  .mw-item-list-compact {
327
- margin-top: spacing('2');
328
- margin-left: spacing('2');
329
- border: none;
330
- border-left: 2px solid var(--mw-border);
331
- border-radius: 0;
332
- background: transparent;
264
+ @extend .mw-item-list;
265
+ gap: 0;
266
+ border: 1px solid var(--mw-border);
267
+ border-radius: radius('md');
268
+ overflow: hidden;
269
+ background: var(--mw-card-background);
333
270
 
334
271
  > * {
335
- padding: spacing('2');
336
- font-size: font-size('sm');
272
+ padding: spacing('3');
273
+ border-bottom: 1px solid var(--mw-border);
274
+ transition:
275
+ background var(--mw-duration-fast) var(--mw-ease-out),
276
+ padding-left var(--mw-duration-fast) var(--mw-ease-out);
277
+ position: relative;
278
+
279
+ // Always present at zero width so it can grow on hover - creating it
280
+ // inside :hover means it snaps in with no transition
281
+ &::before {
282
+ content: '';
283
+ position: absolute;
284
+ left: 0;
285
+ top: 0;
286
+ bottom: 0;
287
+ width: 0;
288
+ background: var(--mw-primary-text-color);
289
+ transition: width var(--mw-duration-fast) var(--mw-ease-out);
290
+ }
291
+
292
+ &:last-child {
293
+ border-bottom: none;
294
+ }
337
295
 
338
296
  &:hover {
339
297
  background: var(--mw-primary-background-hover);
340
298
  padding-left: spacing('4');
341
- border-left: 3px solid var(--mw-primary-text-color);
299
+
300
+ &::before {
301
+ width: 3px;
302
+ }
342
303
  }
343
- }
344
- }
345
- }
346
304
 
347
- // Interactive menu list
348
- .mw-item-list-menu {
349
- @extend .mw-item-list;
350
- gap: spacing('0');
351
- border: 1px solid var(--mw-border);
352
- border-radius: radius('lg');
353
- overflow: hidden;
354
- background: var(--mw-card-background);
355
- box-shadow: var(--mw-elevation-2);
356
-
357
- > * {
358
- padding: spacing('4');
359
- border-bottom: 1px solid var(--mw-border);
360
- transition:
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);
365
- cursor: pointer;
366
- display: flex;
367
- align-items: center;
368
- gap: spacing('2');
305
+ // Handle nested compact lists
306
+ &:has(.mw-item-list-compact) {
307
+ padding-bottom: spacing('1');
369
308
 
370
- &:last-child {
371
- border-bottom: none;
372
- }
309
+ &:hover {
310
+ padding-left: spacing('4');
373
311
 
374
- &:hover {
375
- background: var(--mw-primary-background-hover);
376
- padding-left: spacing('5');
312
+ &::before {
313
+ width: 0;
314
+ }
315
+ }
316
+ }
377
317
  }
378
318
 
379
- &:active {
380
- background: var(--mw-primary-color);
381
- color: var(--mw-primary-accent-text-color);
382
- transform: scale(0.98);
319
+ // Nested compact lists styling - only the left rule, the full border comes
320
+ // from the outer rule and would frame the nested list a second time
321
+ .mw-item-list-compact {
322
+ margin-top: spacing('2');
323
+ margin-left: spacing('2');
324
+ border: none;
325
+ border-left: 2px solid var(--mw-border);
326
+ border-radius: 0;
327
+ background: transparent;
328
+
329
+ > * {
330
+ padding: spacing('2');
331
+ font-size: font-size('sm');
332
+
333
+ &:hover {
334
+ background: var(--mw-primary-background-hover);
335
+ padding-left: spacing('4');
336
+ border-left: 3px solid var(--mw-primary-text-color);
337
+ }
338
+ }
383
339
  }
384
340
  }
385
- }
386
341
 
387
- // Simple scrollable list
388
- .mw-item-list-scroll {
389
- @extend .mw-item-list;
390
- gap: 0;
391
- max-height: 300px;
392
- overflow-y: auto;
393
- border: 1px solid var(--mw-border);
394
- border-radius: radius('md');
395
- background: var(--mw-card-background);
396
- @include _list-scrollbar;
397
-
398
- > * {
399
- padding: spacing('3');
400
- border-bottom: 1px solid var(--mw-border);
401
- transition:
402
- background var(--mw-duration-fast) var(--mw-ease-out),
403
- color var(--mw-duration-fast) var(--mw-ease-out);
404
-
405
- &:last-child {
406
- border-bottom: none;
407
- }
342
+ // Interactive menu list
343
+ .mw-item-list-menu {
344
+ @extend .mw-item-list;
345
+ gap: spacing('0');
346
+ border: 1px solid var(--mw-border);
347
+ border-radius: radius('lg');
348
+ overflow: hidden;
349
+ background: var(--mw-card-background);
350
+ box-shadow: var(--mw-elevation-2);
408
351
 
409
- &:hover {
410
- background: var(--mw-primary-background-hover);
352
+ > * {
353
+ padding: spacing('4');
354
+ border-bottom: 1px solid var(--mw-border);
355
+ transition:
356
+ background var(--mw-duration-fast) var(--mw-ease-out),
357
+ padding-left var(--mw-duration-fast) var(--mw-ease-out),
358
+ color var(--mw-duration-fast) var(--mw-ease-out),
359
+ transform var(--mw-duration-fast) var(--mw-ease-out);
411
360
  cursor: pointer;
412
- }
361
+ display: flex;
362
+ align-items: center;
363
+ gap: spacing('2');
413
364
 
414
- &:active {
415
- background: var(--mw-primary-color);
416
- color: var(--mw-primary-accent-text-color);
417
- }
418
- }
419
- }
365
+ &:last-child {
366
+ border-bottom: none;
367
+ }
420
368
 
421
- // Height modifiers - additive, put them alongside mw-item-list-scroll.
422
- // Extending duplicated the whole scroll block three times over for what is
423
- // one declaration each.
424
- .mw-item-list-scroll-sm {
425
- max-height: 200px;
426
- }
369
+ &:hover {
370
+ background: var(--mw-primary-background-hover);
371
+ padding-left: spacing('5');
372
+ }
427
373
 
428
- .mw-item-list-scroll-lg {
429
- max-height: 400px;
430
- }
374
+ &:active {
375
+ background: var(--mw-primary-color);
376
+ color: var(--mw-primary-accent-text-color);
377
+ transform: scale(0.98);
378
+ }
379
+ }
380
+ }
431
381
 
432
- .mw-item-list-scroll-xl {
433
- max-height: 500px;
434
- }
382
+ // Simple scrollable list
383
+ .mw-item-list-scroll {
384
+ @extend .mw-item-list;
385
+ gap: 0;
386
+ max-height: 300px;
387
+ overflow-y: auto;
388
+ border: 1px solid var(--mw-border);
389
+ border-radius: radius('md');
390
+ background: var(--mw-card-background);
391
+ @include _list-scrollbar;
435
392
 
436
- // Checkbox list component
437
- .mw-item-list-checkbox {
438
- @extend .mw-item-list;
439
- gap: 0;
440
- border: 1px solid var(--mw-border);
441
- border-radius: radius('md');
442
- background: var(--mw-card-background);
443
- overflow: hidden;
393
+ > * {
394
+ padding: spacing('3');
395
+ border-bottom: 1px solid var(--mw-border);
396
+ transition:
397
+ background var(--mw-duration-fast) var(--mw-ease-out),
398
+ color var(--mw-duration-fast) var(--mw-ease-out);
444
399
 
445
- > * {
446
- display: flex;
447
- align-items: center;
448
- padding: spacing('2');
449
- border-bottom: 1px solid var(--mw-border);
450
- border-left: 3px solid transparent;
451
- cursor: pointer;
452
- transition:
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);
457
- user-select: none;
458
-
459
- &:last-child {
460
- border-bottom: none;
461
- }
400
+ &:last-child {
401
+ border-bottom: none;
402
+ }
462
403
 
463
- &:hover {
464
- background: var(--mw-primary-background-hover);
465
- }
404
+ &:hover {
405
+ background: var(--mw-primary-background-hover);
406
+ cursor: pointer;
407
+ }
466
408
 
467
- &:active {
468
- background: var(--mw-primary-color);
469
- color: var(--mw-primary-accent-text-color);
470
- transform: scale(0.98);
409
+ &:active {
410
+ background: var(--mw-primary-color);
411
+ color: var(--mw-primary-accent-text-color);
412
+ }
471
413
  }
414
+ }
472
415
 
473
- // Only the deltas to the .mw-checkbox in form-elements. The hidden input,
474
- // the box chrome and the checked, focus-visible, disabled and color states
475
- // all come from there - copying them here used to shadow disabled and the
476
- // size variants, because the nesting gave the copy a higher specificity.
477
- .mw-checkbox {
478
- display: flex;
479
- gap: spacing('3');
480
- flex: 1;
416
+ // Height modifiers - additive, put them alongside mw-item-list-scroll.
417
+ // Extending duplicated the whole scroll block three times over for what is
418
+ // one declaration each.
419
+ .mw-item-list-scroll-sm {
420
+ max-height: 200px;
421
+ }
481
422
 
482
- // A list checkbox is smaller than a standalone one. Size is a list
483
- // concern here - the -compact and -large list modifiers drive it, not
484
- // mw-checkbox-sm/-lg, which sit on the wrong element to reach this.
485
- .mw-checkbox-box {
486
- width: $_checkbox-box-default;
487
- height: $_checkbox-box-default;
488
- margin-top: $_checkbox-box-offset;
423
+ .mw-item-list-scroll-lg {
424
+ max-height: 400px;
425
+ }
489
426
 
490
- &::after {
491
- width: $_check-default-w;
492
- height: $_check-default-h;
493
- }
494
- }
427
+ .mw-item-list-scroll-xl {
428
+ max-height: 500px;
429
+ }
495
430
 
496
- // Header plus description stacked next to the box - a list-only
497
- // extension, the form element carries a single label
498
- .mw-checkbox-content {
499
- display: flex;
500
- flex-direction: column;
501
- gap: spacing('1');
502
- flex: 1;
431
+ // Checkbox list component
432
+ .mw-item-list-checkbox {
433
+ @extend .mw-item-list;
434
+ gap: 0;
435
+ border: 1px solid var(--mw-border);
436
+ border-radius: radius('md');
437
+ background: var(--mw-card-background);
438
+ overflow: hidden;
503
439
 
504
- .mw-checkbox-header {
505
- font-size: font-size('sm');
506
- font-weight: font-weight('medium');
507
- color: var(--mw-text-color);
508
- line-height: 1.3;
509
- margin: spacing('0');
510
- }
440
+ > * {
441
+ display: flex;
442
+ align-items: center;
443
+ padding: spacing('2');
444
+ border-bottom: 1px solid var(--mw-border);
445
+ border-left: 3px solid transparent;
446
+ cursor: pointer;
447
+ transition:
448
+ background var(--mw-duration-fast) var(--mw-ease-out),
449
+ color var(--mw-duration-fast) var(--mw-ease-out),
450
+ transform var(--mw-duration-fast) var(--mw-ease-out),
451
+ border-left-color var(--mw-duration-fast) var(--mw-ease-out);
452
+ user-select: none;
511
453
 
512
- .mw-checkbox-label {
513
- font-size: font-size('xs');
514
- color: var(--mw-text-muted-color);
515
- line-height: 1.4;
516
- margin: spacing('0');
517
- }
454
+ &:last-child {
455
+ border-bottom: none;
518
456
  }
519
457
 
520
- // When header + description exists, top-align box with text
521
- &:has(.mw-checkbox-header) {
522
- align-items: flex-start;
458
+ &:hover {
459
+ background: var(--mw-primary-background-hover);
523
460
  }
524
461
 
525
- // When only label exists (no header)
526
- &:not(:has(.mw-checkbox-header)) {
527
- align-items: center;
528
-
529
- .mw-checkbox-box {
530
- margin-top: spacing('0');
531
- }
532
-
533
- .mw-checkbox-content {
534
- gap: spacing('0');
535
- }
536
-
537
- .mw-checkbox-label {
538
- font-size: font-size('sm');
539
- color: var(--mw-text-color);
540
- }
462
+ &:active {
463
+ background: var(--mw-primary-color);
464
+ color: var(--mw-primary-accent-text-color);
465
+ transform: scale(0.98);
541
466
  }
542
- }
543
-
544
- // When item is selected, add visual feedback
545
- &.mw-selected {
546
- background: var(--mw-primary-background-hover);
547
- border-left-color: var(--mw-primary-text-color);
548
- }
549
- }
550
-
551
- // Compact variant
552
- &-compact {
553
- > * {
554
- padding: spacing('1') spacing('3');
555
467
 
468
+ // Only the deltas to the .mw-checkbox in form-elements. The hidden input,
469
+ // the box chrome and the checked, focus-visible, disabled and color states
470
+ // all come from there - copying them here used to shadow disabled and the
471
+ // size variants, because the nesting gave the copy a higher specificity.
556
472
  .mw-checkbox {
557
- gap: spacing('1');
473
+ display: flex;
474
+ gap: spacing('3');
475
+ flex: 1;
558
476
 
477
+ // A list checkbox is smaller than a standalone one. Size is a list
478
+ // concern here - the -compact and -large list modifiers drive it, not
479
+ // mw-checkbox-sm/-lg, which sit on the wrong element to reach this.
559
480
  .mw-checkbox-box {
560
- width: $_checkbox-box-compact;
561
- height: $_checkbox-box-compact;
562
- margin-top: spacing('1');
481
+ width: $_checkbox-box-default;
482
+ height: $_checkbox-box-default;
483
+ margin-top: $_checkbox-box-offset;
563
484
 
564
485
  &::after {
565
- width: $_check-compact-w;
566
- height: $_check-compact-h;
486
+ width: $_check-default-w;
487
+ height: $_check-default-h;
567
488
  }
568
489
  }
569
490
 
491
+ // Header plus description stacked next to the box - a list-only
492
+ // extension, the form element carries a single label
570
493
  .mw-checkbox-content {
494
+ display: flex;
495
+ flex-direction: column;
571
496
  gap: spacing('1');
497
+ flex: 1;
572
498
 
573
499
  .mw-checkbox-header {
574
- font-size: font-size('xs');
500
+ font-size: font-size('sm');
575
501
  font-weight: font-weight('medium');
502
+ color: var(--mw-text-color);
503
+ line-height: 1.3;
504
+ margin: spacing('0');
576
505
  }
577
506
 
578
507
  .mw-checkbox-label {
579
- font-size: font-size('2xs');
508
+ font-size: font-size('xs');
509
+ color: var(--mw-text-muted-color);
510
+ line-height: 1.4;
511
+ margin: spacing('0');
580
512
  }
581
513
  }
582
514
 
583
- // When only label exists in compact
515
+ // When header + description exists, top-align box with text
516
+ &:has(.mw-checkbox-header) {
517
+ align-items: flex-start;
518
+ }
519
+
520
+ // When only label exists (no header)
584
521
  &:not(:has(.mw-checkbox-header)) {
522
+ align-items: center;
523
+
585
524
  .mw-checkbox-box {
586
- margin-top: 0;
525
+ margin-top: spacing('0');
526
+ }
527
+
528
+ .mw-checkbox-content {
529
+ gap: spacing('0');
587
530
  }
588
531
 
589
532
  .mw-checkbox-label {
590
- font-size: font-size('xs');
533
+ font-size: font-size('sm');
534
+ color: var(--mw-text-color);
591
535
  }
592
536
  }
593
537
  }
594
- }
595
- }
596
538
 
597
- // Large variant
598
- &-large {
599
- > * {
600
- padding: spacing('4') spacing('4');
539
+ // When item is selected, add visual feedback
540
+ &.mw-selected {
541
+ background: var(--mw-primary-background-hover);
542
+ border-left-color: var(--mw-primary-text-color);
543
+ }
544
+ }
601
545
 
602
- .mw-checkbox {
603
- gap: spacing('3');
546
+ // Compact variant
547
+ &-compact {
548
+ > * {
549
+ padding: spacing('1') spacing('3');
604
550
 
605
- .mw-checkbox-box {
606
- width: $_checkbox-box-large;
607
- height: $_checkbox-box-large;
608
- margin-top: spacing('1');
551
+ .mw-checkbox {
552
+ gap: spacing('1');
609
553
 
610
- &::after {
611
- width: $_check-large-w;
612
- height: $_check-large-h;
554
+ .mw-checkbox-box {
555
+ width: $_checkbox-box-compact;
556
+ height: $_checkbox-box-compact;
557
+ margin-top: spacing('1');
558
+
559
+ &::after {
560
+ width: $_check-compact-w;
561
+ height: $_check-compact-h;
562
+ }
613
563
  }
614
- }
615
564
 
616
- .mw-checkbox-content {
617
- gap: spacing('1');
565
+ .mw-checkbox-content {
566
+ gap: spacing('1');
618
567
 
619
- .mw-checkbox-header {
620
- font-size: font-size('base');
621
- font-weight: font-weight('medium');
568
+ .mw-checkbox-header {
569
+ font-size: font-size('xs');
570
+ font-weight: font-weight('medium');
571
+ }
572
+
573
+ .mw-checkbox-label {
574
+ font-size: font-size('2xs');
575
+ }
622
576
  }
623
577
 
624
- .mw-checkbox-label {
625
- font-size: font-size('sm');
578
+ // When only label exists in compact
579
+ &:not(:has(.mw-checkbox-header)) {
580
+ .mw-checkbox-box {
581
+ margin-top: 0;
582
+ }
583
+
584
+ .mw-checkbox-label {
585
+ font-size: font-size('xs');
586
+ }
626
587
  }
627
588
  }
589
+ }
590
+ }
591
+
592
+ // Large variant
593
+ &-large {
594
+ > * {
595
+ padding: spacing('4') spacing('4');
596
+
597
+ .mw-checkbox {
598
+ gap: spacing('3');
628
599
 
629
- // When only label exists in large
630
- &:not(:has(.mw-checkbox-header)) {
631
600
  .mw-checkbox-box {
632
- margin-top: spacing('0');
601
+ width: $_checkbox-box-large;
602
+ height: $_checkbox-box-large;
603
+ margin-top: spacing('1');
604
+
605
+ &::after {
606
+ width: $_check-large-w;
607
+ height: $_check-large-h;
608
+ }
633
609
  }
634
610
 
635
- .mw-checkbox-label {
636
- font-size: font-size('base');
611
+ .mw-checkbox-content {
612
+ gap: spacing('1');
613
+
614
+ .mw-checkbox-header {
615
+ font-size: font-size('base');
616
+ font-weight: font-weight('medium');
617
+ }
618
+
619
+ .mw-checkbox-label {
620
+ font-size: font-size('sm');
621
+ }
622
+ }
623
+
624
+ // When only label exists in large
625
+ &:not(:has(.mw-checkbox-header)) {
626
+ .mw-checkbox-box {
627
+ margin-top: spacing('0');
628
+ }
629
+
630
+ .mw-checkbox-label {
631
+ font-size: font-size('base');
632
+ }
637
633
  }
638
634
  }
639
635
  }
640
636
  }
641
637
  }
642
- }
643
638
 
644
- // Color variants for checkbox lists - additive, sits alongside
645
- // mw-item-list-checkbox
646
- .mw-item-list-checkbox-secondary {
647
- > * {
648
- &:hover {
649
- background: var(--mw-secondary-background-hover);
650
- }
639
+ // Color variants for checkbox lists - additive, sits alongside
640
+ // mw-item-list-checkbox
641
+ .mw-item-list-checkbox-secondary {
642
+ > * {
643
+ &:hover {
644
+ background: var(--mw-secondary-background-hover);
645
+ }
651
646
 
652
- &:active {
653
- background: var(--mw-secondary-color);
654
- color: var(--mw-secondary-accent-text-color);
655
- }
647
+ &:active {
648
+ background: var(--mw-secondary-color);
649
+ color: var(--mw-secondary-accent-text-color);
650
+ }
656
651
 
657
- &.mw-selected {
658
- background: var(--mw-secondary-background-hover);
659
- border-left-color: var(--mw-secondary-text-color);
652
+ &.mw-selected {
653
+ background: var(--mw-secondary-background-hover);
654
+ border-left-color: var(--mw-secondary-text-color);
655
+ }
660
656
  }
661
657
  }
662
- }
663
658
 
664
- // Scrollable checkbox list
665
- .mw-item-list-checkbox-scroll {
666
- @extend .mw-item-list-checkbox;
667
- max-height: 300px;
668
- overflow-y: auto;
669
- @include _list-scrollbar;
659
+ // Scrollable checkbox list
660
+ .mw-item-list-checkbox-scroll {
661
+ @extend .mw-item-list-checkbox;
662
+ max-height: 300px;
663
+ overflow-y: auto;
664
+ @include _list-scrollbar;
665
+ }
670
666
  }