maverick-wave 5.11.0 → 5.13.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 (32) hide show
  1. package/.claude/skills/mw-maverick-wave/SKILL.md +63 -8
  2. package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +6 -3
  3. package/.claude/skills/mw-maverick-wave/references/components.md +41 -27
  4. package/.claude/skills/mw-maverick-wave/references/javascript.md +27 -26
  5. package/.claude/skills/mw-maverick-wave/references/layout.md +12 -6
  6. package/.claude/skills/mw-maverick-wave/references/theming.md +59 -4
  7. package/CHANGELOG.md +18 -0
  8. package/README.md +45 -5
  9. package/index.html +12 -11
  10. package/maverick-wave.min.css +4 -4
  11. package/maverick-wave.min.js +1 -1
  12. package/package.json +2 -2
  13. package/src/js/main.js +67 -20
  14. package/src/partials/buttons-container.html +2 -1
  15. package/src/partials/get-started-container.html +52 -3
  16. package/src/partials/palette-container.html +23 -8
  17. package/src/partials/parallax-container.html +8 -5
  18. package/src/partials/tabs-container.html +1 -1
  19. package/src/partials/typography-container.html +3 -0
  20. package/src/scss/abstracts/_functions.scss +50 -0
  21. package/src/scss/abstracts/_mixins.scss +33 -0
  22. package/src/scss/base/_typography.scss +4 -21
  23. package/src/scss/components/_buttons.scss +1 -1
  24. package/src/scss/components/_content-slider.scss +16 -8
  25. package/src/scss/components/_dropdown.scss +1 -1
  26. package/src/scss/components/_gallery.scss +13 -2
  27. package/src/scss/components/_lang-switch.scss +1 -1
  28. package/src/scss/components/_segmented.scss +4 -0
  29. package/src/scss/layout/_header.scss +3 -2
  30. package/src/scss/layout/_parallax.scss +18 -2
  31. package/src/scss/layout/_section.scss +2 -10
  32. package/src/scss/utilities/_touch-targets.scss +22 -16
@@ -9,21 +9,29 @@
9
9
  border-radius: radius('md');
10
10
  overflow: hidden;
11
11
 
12
+ // The slider caps at 600px, so past a tablet the viewport no longer says how
13
+ // much room it has. Named, so a query cannot resolve to a container above.
14
+ container: mw-slider / inline-size;
15
+
12
16
  // Heights variables for consistency
13
17
  $height-lg: 370px;
14
18
  $height-md: 320px;
15
19
  $height-sm: 250px;
16
20
 
21
+ // The slider widths the old viewport steps landed on, not the breakpoints
22
+ $wide: 560px;
23
+ $mid: 420px;
24
+
17
25
  &-base {
18
26
  position: relative;
19
27
  width: 100%;
20
28
  height: $height-sm;
21
29
 
22
- @include media-up('sm') {
30
+ @container mw-slider (width >= #{$mid}) {
23
31
  height: $height-md;
24
32
  }
25
33
 
26
- @include media-up('md') {
34
+ @container mw-slider (width >= #{$wide}) {
27
35
  height: $height-lg;
28
36
  }
29
37
  }
@@ -43,11 +51,11 @@
43
51
  height: $height-sm;
44
52
  pointer-events: none;
45
53
 
46
- @include media-up('sm') {
54
+ @container mw-slider (width >= #{$mid}) {
47
55
  height: $height-md;
48
56
  }
49
57
 
50
- @include media-up('md') {
58
+ @container mw-slider (width >= #{$wide}) {
51
59
  height: $height-lg;
52
60
  }
53
61
  }
@@ -86,11 +94,11 @@
86
94
  z-index: z-index('menu');
87
95
  width: 100%;
88
96
 
89
- @include media-up('sm') {
97
+ @container mw-slider (width >= #{$mid}) {
90
98
  grid-template-columns: repeat(3, 1fr);
91
99
  }
92
100
 
93
- @include media-up('md') {
101
+ @container mw-slider (width >= #{$wide}) {
94
102
  gap: spacing('3');
95
103
  padding: spacing('3');
96
104
  }
@@ -106,11 +114,11 @@
106
114
  z-index: z-index('menu');
107
115
  width: 100%;
108
116
 
109
- @include media-up('sm') {
117
+ @container mw-slider (width >= #{$mid}) {
110
118
  grid-template-columns: repeat(2, 1fr);
111
119
  }
112
120
 
113
- @include media-up('md') {
121
+ @container mw-slider (width >= #{$wide}) {
114
122
  gap: spacing('3');
115
123
  padding: spacing('3');
116
124
  }
@@ -257,7 +257,7 @@
257
257
  // A menu opened by a thumb needs rows a thumb can hit, and the room to show
258
258
  // them - so it takes the trigger's full width rather than a 200px column
259
259
  // floating beside it.
260
- @media (pointer: coarse), (width <= #{breakpoint('sm')}) {
260
+ @include touch-context('sm') {
261
261
  .mw-dropdown-menu {
262
262
  min-width: max(100%, 240px);
263
263
  }
@@ -1,9 +1,20 @@
1
1
  @use '../abstracts' as *;
2
2
 
3
3
  @layer mw.components {
4
+ // Thresholds are the wrapper widths the old viewport steps landed on once the
5
+ // container gutter is taken off, not the breakpoints themselves.
6
+ $wide: 688px;
7
+ $narrow: 512px;
8
+
4
9
  .mw-gallery-container {
5
10
  max-width: 1100px;
11
+ // Inline-size containment computes the width as if the element were empty,
12
+ // so one dropped into a flex or grid slot would shrink to nothing without it
13
+ width: 100%;
6
14
  margin: spacing('1') auto;
15
+ // The wrapper and not .mw-gallery: the description and the dots are its
16
+ // siblings, and a container query only reaches descendants
17
+ container: mw-gallery / inline-size;
7
18
  }
8
19
 
9
20
  .mw-gallery {
@@ -119,7 +130,7 @@
119
130
  }
120
131
  }
121
132
 
122
- @include media-down('md') {
133
+ @container mw-gallery (width < #{$wide}) {
123
134
  .mw-gallery {
124
135
  &-desc {
125
136
  font-size: font-size('sm');
@@ -134,7 +145,7 @@
134
145
  }
135
146
  }
136
147
 
137
- @include media-down('sm') {
148
+ @container mw-gallery (width < #{$narrow}) {
138
149
  .mw-gallery {
139
150
  &-slide {
140
151
  aspect-ratio: 4 / 3;
@@ -52,7 +52,7 @@
52
52
  .mw-lang-switch .mw-dropdown-menu {
53
53
  min-width: 170px;
54
54
 
55
- @media (pointer: coarse), (width <= #{breakpoint('sm')}) {
55
+ @include touch-context('sm') {
56
56
  min-width: max(100%, 240px);
57
57
  }
58
58
  }
@@ -92,6 +92,10 @@
92
92
  // the width of the shortest, so the items follow their own content instead.
93
93
  .mw-segmented-auto {
94
94
  width: auto;
95
+ // Shrink-to-fit sizes this off the labels, which on a 320px screen is wider
96
+ // than the screen. The items already carry `min-width: 0` and truncate, so
97
+ // the cap only ever bites where the row genuinely has no room.
98
+ max-width: 100%;
95
99
 
96
100
  .mw-segmented-item {
97
101
  flex: 0 1 auto;
@@ -231,9 +231,10 @@
231
231
  // Keeps a rubber-band scroll inside the panel from moving the page
232
232
  overscroll-behavior: contain;
233
233
  padding: calc(
234
- var(--mw-header-height) + #{spacing('6')} + env(safe-area-inset-top)
234
+ var(--mw-header-height) + #{spacing('6')} +
235
+ env(safe-area-inset-top, 0px)
235
236
  )
236
- spacing('4') calc(#{spacing('6')} + env(safe-area-inset-bottom));
237
+ spacing('4') calc(#{spacing('6')} + env(safe-area-inset-bottom, 0px));
237
238
  }
238
239
 
239
240
  .mw-navbar-item {
@@ -24,7 +24,7 @@
24
24
  position: relative;
25
25
  display: flex;
26
26
  align-items: center;
27
- min-height: 42vh;
27
+ min-height: 60vh;
28
28
  // `clip` and never `hidden`: hidden makes this a scroll container, and the
29
29
  // view() timeline below would then resolve against this box instead of the
30
30
  // viewport - the layer keeps its overhang and never moves
@@ -148,11 +148,27 @@
148
148
  background: var(--mw-page-background);
149
149
  }
150
150
 
151
+ // `+` and not `~` like the two rules above: only the section that does the
152
+ // overtaking carries the edge, on every one after it the shadow would read as
153
+ // a seam across the page. Fixed values and not elevation(): this shadow lands
154
+ // on the picture rather than on a theme surface, and the light theme's 21%
155
+ // near layer disappears there - same reason mw-parallax-dimmed below
156
+ // hardcodes its brightness and its text-shadow.
157
+ :where(
158
+ :is(.mw-parallax-sticky, .mw-parallax-slow) + *:not(.mw-parallax-sticky)
159
+ ) {
160
+ box-shadow:
161
+ 0 -6px 12px rgb(0 0 0 / 45%),
162
+ 0 -20px 44px rgb(0 0 0 / 26%);
163
+ }
164
+
151
165
  // Ink on a photograph, the same pair the hero uses: the picture goes down, the
152
166
  // text goes light. A band without content on it needs neither.
153
167
  .mw-parallax-dimmed {
154
168
  > .mw-parallax-media {
155
- filter: brightness(0.5);
169
+ // $hero-filter-dark's value, not the token: that one flips to 1.1 in the
170
+ // light theme, and this band's ink stays light in both
171
+ filter: brightness(0.7);
156
172
  }
157
173
 
158
174
  > .mw-parallax-content {
@@ -24,16 +24,12 @@
24
24
  }
25
25
 
26
26
  .mw-section-title {
27
- font-size: font-size('2xl');
27
+ font-size: fluid('2xl', '3xl', $to: 'sm');
28
28
  margin-bottom: var(--mw-section-title-gap);
29
29
  text-align: center;
30
30
  position: relative;
31
31
 
32
32
  @include _section-rule(56px, 3px, spacing('-3'));
33
-
34
- @include media-up('sm') {
35
- font-size: font-size('3xl');
36
- }
37
33
  }
38
34
 
39
35
  // The lead line under a section title. Every landing page writes this
@@ -51,7 +47,7 @@
51
47
  }
52
48
 
53
49
  .mw-section-subtitle {
54
- font-size: font-size('xl');
50
+ font-size: fluid('xl', '2xl', $to: 'sm');
55
51
  // The step above a demo gap of spacing('6') - at spacing('8') the boundary
56
52
  // between two components read like the one between two demos
57
53
  margin: spacing('10') spacing('0') spacing('6') spacing('0');
@@ -64,10 +60,6 @@
64
60
  spacing('-2'),
65
61
  var(--mw-secondary-text-color)
66
62
  );
67
-
68
- @include media-up('sm') {
69
- font-size: font-size('2xl');
70
- }
71
63
  }
72
64
 
73
65
  // Sticky, because the strip is the only way back: inside a long section the
@@ -2,10 +2,9 @@
2
2
 
3
3
  @layer mw.utilities {
4
4
  // WCAG 2.5.8 puts the floor at 24x24px, and a floor is not a goal - the compact
5
- // sizes are right under a pointer and too small under a thumb. Coarse *or*
6
- // narrow, because a tablet in landscape is wide and still finger-operated.
5
+ // sizes are right under a pointer and too small under a thumb.
7
6
  // Loaded last, so these win without extra specificity.
8
- @media (pointer: coarse), (width <= #{breakpoint('md')}) {
7
+ @include touch-context {
9
8
  // Padding and line-height add up to ~35px, under the 44px a thumb needs. Only
10
9
  // the height grows: the padding sets the label's relationship to the edges.
11
10
  .mw-btn {
@@ -85,13 +84,7 @@
85
84
  }
86
85
 
87
86
  .mw-gallery-dot {
88
- position: relative;
89
-
90
- &::after {
91
- content: '';
92
- position: absolute;
93
- inset: -7.5px;
94
- }
87
+ @include hit-area(7.5px);
95
88
  }
96
89
 
97
90
  // A range input is as tall as its track, so the whole hit area is 8px and you
@@ -109,14 +102,27 @@
109
102
  // area grows, to 28px - clear of the 24px floor. The extra margin keeps two
110
103
  // neighbouring hit areas from overlapping.
111
104
  .mw-btn-mini {
112
- position: relative;
113
105
  margin-left: spacing('4');
106
+ @include hit-area(5px);
107
+ }
108
+
109
+ // Edit and delete on a ticket. The 32px box stays - a 44px one would push
110
+ // the assignee off the card footer - and the row carries the gap the two
111
+ // grown hit areas need, or they overlap and a tap meant for edit deletes.
112
+ .mw-kanban-card-actions {
113
+ gap: spacing('4');
114
+ }
114
115
 
115
- &::after {
116
- content: '';
117
- position: absolute;
118
- inset: -5px;
119
- }
116
+ .mw-kanban-action {
117
+ @include hit-area(6px);
118
+ }
119
+
120
+ // The box itself and not a hit area over it: half of these carry a
121
+ // `data-tooltip`, which owns both pseudo-elements, so the trick above lands
122
+ // on some of the logos and silently skips the rest.
123
+ .mw-techstack-item-sm {
124
+ min-width: 2.5rem;
125
+ min-height: 2.5rem;
120
126
  }
121
127
  }
122
128