maverick-wave 4.6.0 → 4.7.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,16 +1,16 @@
1
1
  {
2
2
  "name": "maverick-wave",
3
- "version": "4.6.0",
3
+ "version": "4.7.0",
4
4
  "config": {
5
- "version_short": "4.6"
5
+ "version_short": "4.7"
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",
9
9
  "style": "src/scss/main.scss",
10
10
  "scripts": {
11
11
  "clean": "gulp clean",
12
- "format": "prettier --write \"**/*.{scss,js,json,html,md}\"",
13
- "format:check": "prettier --check \"**/*.{scss,js,json,html,md}\"",
12
+ "format": "prettier --check \"**/*.{scss,js,json,html,md}\"",
13
+ "format:fix": "prettier --write \"**/*.{scss,js,json,html,md}\"",
14
14
  "showcase": "http-server -c-1 -p 8888 dist",
15
15
  "start": "gulp",
16
16
  "build": "gulp clean && gulp build",
@@ -38,9 +38,9 @@
38
38
  ],
39
39
  "devDependencies": {
40
40
  "autoprefixer": "^10.4.21",
41
+ "cssnano": "^8.0.7",
41
42
  "del": "^8.0.1",
42
43
  "gulp": "^5.0.0",
43
- "gulp-clean-css": "^4.3.0",
44
44
  "gulp-file-include": "^2.3.0",
45
45
  "gulp-postcss": "^10.0.0",
46
46
  "gulp-rename": "^2.1.0",
@@ -5,43 +5,46 @@
5
5
  <h4 class="mw-mb-2">Basic Table</h4>
6
6
  <p class="mw-text-muted">
7
7
  This is the basic table that supports all functions except the complete
8
- responsive feeling with the cards
8
+ responsive feeling with the cards - five columns do not fit a phone, so it
9
+ sits in a <code>mw-table-responsive</code> wrapper
9
10
  </p>
10
11
 
11
- <table class="mw-table">
12
- <thead>
13
- <tr>
14
- <th>#</th>
15
- <th>Name</th>
16
- <th>Position</th>
17
- <th>Location</th>
18
- <th class="mw-text-currency">Budget</th>
19
- </tr>
20
- </thead>
21
- <tbody>
22
- <tr>
23
- <td>1</td>
24
- <td>John Doe</td>
25
- <td>Developer</td>
26
- <td>New York</td>
27
- <td class="mw-text-currency">1,204.50</td>
28
- </tr>
29
- <tr>
30
- <td>2</td>
31
- <td>Jane Smith</td>
32
- <td>Designer</td>
33
- <td>London</td>
34
- <td class="mw-text-currency">87.00</td>
35
- </tr>
36
- <tr>
37
- <td>3</td>
38
- <td>Bob Johnson</td>
39
- <td>Manager</td>
40
- <td>Berlin</td>
41
- <td class="mw-text-currency">15,930.25</td>
42
- </tr>
43
- </tbody>
44
- </table>
12
+ <div class="mw-table-responsive">
13
+ <table class="mw-table">
14
+ <thead>
15
+ <tr>
16
+ <th>#</th>
17
+ <th>Name</th>
18
+ <th>Position</th>
19
+ <th>Location</th>
20
+ <th class="mw-text-currency">Budget</th>
21
+ </tr>
22
+ </thead>
23
+ <tbody>
24
+ <tr>
25
+ <td>1</td>
26
+ <td>John Doe</td>
27
+ <td>Developer</td>
28
+ <td>New York</td>
29
+ <td class="mw-text-currency">1,204.50</td>
30
+ </tr>
31
+ <tr>
32
+ <td>2</td>
33
+ <td>Jane Smith</td>
34
+ <td>Designer</td>
35
+ <td>London</td>
36
+ <td class="mw-text-currency">87.00</td>
37
+ </tr>
38
+ <tr>
39
+ <td>3</td>
40
+ <td>Bob Johnson</td>
41
+ <td>Manager</td>
42
+ <td>Berlin</td>
43
+ <td class="mw-text-currency">15,930.25</td>
44
+ </tr>
45
+ </tbody>
46
+ </table>
47
+ </div>
45
48
  <p class="mw-text-muted mw-mt-3">
46
49
  The <strong>Budget</strong> column uses
47
50
  <strong>mw-text-currency</strong> - right-aligned with tabular, lining
@@ -51,11 +51,27 @@ $_active-prefix: 'dark';
51
51
  // Layout knobs. A good default is not enough here: what reads as generous on
52
52
  // a landing page costs visible content in an application with a sticky
53
53
  // header. Same framework, two different right answers.
54
- --mw-container-width: min(1200px, 89%);
55
- // Below 'sm' the percentage turns into wasted margin - 89% of a 375px screen
56
- // leaves 41px of nothing on a card that has to fit amount, status and two
57
- // labels into one row. A fixed gutter uses the width instead.
58
- --mw-container-width-sm: calc(100% - #{spacing('5')} * 2);
54
+ //
55
+ // The page gutter is fluid rather than stepped. A plain percentage keeps too
56
+ // little on a phone and throws away too much on a desktop; a fixed gutter
57
+ // does the reverse - Bootstrap ships 12px at every width, Bulma 32px, and
58
+ // Material asks for 16dp on a phone and more as the screen grows. The ramp
59
+ // below lands on ~24px at 375px, ~32px at 576px, ~40px on a tablet and tops
60
+ // out at 64px, where the 1200px cap takes over. Stepping it at a breakpoint
61
+ // instead would make the container jump *backwards* at the step, because the
62
+ // gutter grows faster there than the viewport does.
63
+ //
64
+ // max() against the safe-area insets, so a notched phone in landscape pushes
65
+ // the content clear of the cutout instead of running underneath it.
66
+ --mw-container-gutter: max(
67
+ clamp(1rem, 4.2vw + 0.5rem, 4rem),
68
+ env(safe-area-inset-left, 0px),
69
+ env(safe-area-inset-right, 0px)
70
+ );
71
+ --mw-container-width: min(
72
+ 1200px,
73
+ calc(100% - 2 * var(--mw-container-gutter))
74
+ );
59
75
  --mw-section-padding-block: #{spacing('7')};
60
76
 
61
77
  // Active theme - aliases onto the dark or light set above
@@ -10,7 +10,7 @@
10
10
 
11
11
  html {
12
12
  scroll-behavior: smooth;
13
- min-width: 375px;
13
+ min-width: 320px;
14
14
  // Keeps anchor targets clear of the fixed header, plus a bit of breathing room
15
15
  scroll-padding-top: calc(var(--mw-header-height) + #{spacing('4')});
16
16
  -webkit-text-size-adjust: 100%;
@@ -27,9 +27,16 @@ h6 {
27
27
  font-weight: font-weight('bold');
28
28
  }
29
29
 
30
+ // Two steps, not one. With the single jump at 576px, everything between there
31
+ // and a tablet kept the full desktop headline - 3rem of h1 across a 690px
32
+ // column is a third of the screen before the first line of copy.
30
33
  h1 {
31
34
  font-size: font-size('5xl');
32
35
 
36
+ @include media-down('md') {
37
+ font-size: font-size('4xl');
38
+ }
39
+
33
40
  @include media-down('sm') {
34
41
  font-size: font-size('3xl');
35
42
  }
@@ -38,6 +45,10 @@ h1 {
38
45
  h2 {
39
46
  font-size: font-size('4xl');
40
47
 
48
+ @include media-down('md') {
49
+ font-size: font-size('3xl');
50
+ }
51
+
41
52
  @include media-down('sm') {
42
53
  font-size: font-size('2xl');
43
54
  }
@@ -1,6 +1,7 @@
1
1
  @use '../abstracts' as *;
2
2
 
3
3
  .mw-blog-post {
4
+ position: relative;
4
5
  margin: spacing('2');
5
6
  padding: spacing('4') spacing('7');
6
7
  animation: pageReveal 1.6s ease-out forwards;
@@ -22,6 +23,11 @@
22
23
  }
23
24
  }
24
25
 
26
+ @include media-down('sm') {
27
+ margin: spacing('1');
28
+ padding: spacing('4') spacing('5');
29
+ }
30
+
25
31
  // Book-like left border
26
32
  &::before {
27
33
  content: '';
@@ -48,7 +54,8 @@
48
54
  position: absolute;
49
55
  bottom: spacing('-2');
50
56
  left: spacing('0');
51
- width: 200px;
57
+ // Never wider than the title it underlines
58
+ width: min(200px, 100%);
52
59
  height: 5px;
53
60
  background: var(--mw-primary-text-color);
54
61
  }
@@ -1,5 +1,8 @@
1
1
  @use '../abstracts' as *;
2
2
 
3
+ // Card width at which the footer stops being a row
4
+ $_mw-card-narrow: 360px;
5
+
3
6
  $_mw-card-addon-colors: (
4
7
  primary: var(--mw-primary-color),
5
8
  secondary: var(--mw-secondary-color),
@@ -43,6 +46,19 @@ $_mw-card-addon-colors: (
43
46
  overflow: hidden;
44
47
  }
45
48
 
49
+ // Query container for the footer below. Named, so the query cannot resolve to
50
+ // a project's own container further up the tree.
51
+ //
52
+ // Only cards that have a footer, and they claim their slot: inline-size
53
+ // containment computes the card's own width as if it were empty, so a card
54
+ // that takes its width from its content - a flex row, `mw-grid-stack`, a
55
+ // timeline wrapper - would collapse to its border. Filling the slot keeps the
56
+ // width external, which is what makes it queryable in the first place.
57
+ &:has(.mw-card-footer) {
58
+ width: 100%;
59
+ container: mw-card / inline-size;
60
+ }
61
+
46
62
  &:hover {
47
63
  transform: translateY(-2px);
48
64
  box-shadow: 0 7px 15px var(--mw-shadow);
@@ -120,13 +136,17 @@ $_mw-card-addon-colors: (
120
136
 
121
137
  &-lg {
122
138
  --mw-card-img-height: 340px;
139
+
140
+ @include media-down('sm') {
141
+ --mw-card-img-height: 260px;
142
+ }
123
143
  }
124
144
 
125
145
  &-xl {
126
146
  --mw-card-img-height: 480px;
127
147
 
128
148
  @include media-down('sm') {
129
- --mw-card-img-height: 440px;
149
+ --mw-card-img-height: 340px;
130
150
  }
131
151
  }
132
152
 
@@ -191,6 +211,9 @@ $_mw-card-addon-colors: (
191
211
  // centered, so plain text next to a button sits on the button's centre
192
212
  // line instead of being stretched to its height and starting at the top
193
213
  align-items: center;
214
+ // Buttons do not shrink, so two that no longer fit have to wrap - without
215
+ // this they leave the card sideways
216
+ flex-wrap: wrap;
194
217
  gap: spacing('3');
195
218
  flex-shrink: 0;
196
219
  text-wrap: balance;
@@ -206,11 +229,27 @@ $_mw-card-addon-colors: (
206
229
  flex-shrink: 0;
207
230
  }
208
231
 
209
- @include media-down('lg') {
232
+ // Stacked once the card is narrow, not once the window is - a card in a
233
+ // three-column grid on a wide desktop is as narrow as the same card on a
234
+ // phone and used to keep its actions in a cramped row anyway.
235
+ @container mw-card (max-width: #{$_mw-card-narrow}) {
210
236
  flex-direction: column;
211
237
  align-items: stretch;
212
238
  gap: spacing('2');
213
239
 
240
+ // `flex: 1 0 100%` on the note is 100% of the *height* in a column: it
241
+ // fills the column and the buttons wrap out of the card sideways
242
+ &:has(.mw-actions-note),
243
+ &:has(.mw-form-actions-hint) {
244
+ flex-wrap: nowrap;
245
+ }
246
+
247
+ .mw-actions-note,
248
+ .mw-form-actions-hint {
249
+ flex: 0 0 auto;
250
+ text-align: left;
251
+ }
252
+
214
253
  > * {
215
254
  width: 100%;
216
255
  }
@@ -10,6 +10,12 @@
10
10
  align-items: center;
11
11
  justify-content: flex-end;
12
12
  row-gap: spacing('1');
13
+
14
+ @include media-down('sm') {
15
+ justify-content: flex-start;
16
+ column-gap: spacing('6');
17
+ row-gap: spacing('2');
18
+ }
13
19
  }
14
20
 
15
21
  &-item {
@@ -19,6 +25,10 @@
19
25
  gap: spacing('2');
20
26
  &:not(:first-child) {
21
27
  margin-left: spacing('9');
28
+
29
+ @include media-down('sm') {
30
+ margin-left: spacing('0');
31
+ }
22
32
  }
23
33
  font-size: font-size('md');
24
34
 
@@ -13,7 +13,7 @@
13
13
  display: none;
14
14
  align-items: center;
15
15
  justify-content: center;
16
- padding: spacing('3');
16
+ padding: spacing('7');
17
17
  opacity: 0;
18
18
  transition: opacity 0.4s ease;
19
19
 
@@ -58,6 +58,21 @@
58
58
  }
59
59
  }
60
60
 
61
+ @include media-down('sm') {
62
+ .mw-modal-overlay {
63
+ padding: spacing('5');
64
+ }
65
+
66
+ .mw-modal-header,
67
+ .mw-modal-footer {
68
+ padding: spacing('3') spacing('4');
69
+ }
70
+
71
+ .mw-modal-body {
72
+ padding: spacing('4');
73
+ }
74
+ }
75
+
61
76
  // Modal sections
62
77
  .mw-modal-header {
63
78
  padding: spacing('3') spacing('5');
@@ -92,6 +107,9 @@
92
107
  padding: spacing('3') spacing('5');
93
108
  border-top: 1px solid var(--mw-border-accent);
94
109
  display: flex;
110
+ // Three actions do not fit one line inside a phone-width dialog, and a row
111
+ // that cannot wrap pushes the last one out through the border
112
+ flex-wrap: wrap;
95
113
  gap: spacing('2');
96
114
  justify-content: flex-end;
97
115
  }
@@ -35,6 +35,9 @@
35
35
  }
36
36
 
37
37
  @include media-down('sm') {
38
+ width: 100%;
39
+ margin-inline: spacing('0');
40
+
38
41
  th,
39
42
  td {
40
43
  padding: spacing('1') spacing('2');
@@ -15,7 +15,8 @@
15
15
 
16
16
  @include media-down('sm') {
17
17
  grid-template-columns: 1fr;
18
- width: 90%;
18
+ width: 100%;
19
+ padding: spacing('0');
19
20
  gap: spacing('4');
20
21
  }
21
22
 
@@ -34,7 +35,10 @@
34
35
 
35
36
  @include media-down('sm') {
36
37
  grid-template-columns: 1fr;
37
- width: 90%;
38
+ // Full width from here on - the page gutter is the container's job,
39
+ // a second inset only narrows the tile
40
+ width: 100%;
41
+ padding: spacing('0');
38
42
  gap: spacing('4');
39
43
  }
40
44
  }
@@ -46,7 +50,10 @@
46
50
 
47
51
  @include media-down('sm') {
48
52
  grid-template-columns: 1fr;
49
- width: 90%;
53
+ // Full width from here on - the page gutter is the container's job,
54
+ // a second inset only narrows the tile
55
+ width: 100%;
56
+ padding: spacing('0');
50
57
  gap: spacing('4');
51
58
  }
52
59
  }
@@ -193,6 +193,8 @@ $_simple-date-width: 110px;
193
193
  }
194
194
 
195
195
  @include media-down('sm') {
196
+ width: 100%;
197
+
196
198
  // Line moves to the left
197
199
  &::before {
198
200
  left: 0;
@@ -317,6 +319,8 @@ $_simple-date-width: 110px;
317
319
  }
318
320
 
319
321
  @include media-down('sm') {
322
+ width: 100%;
323
+
320
324
  &::before {
321
325
  left: 0;
322
326
  transform: none;
@@ -53,6 +53,18 @@
53
53
  // full-width stacked
54
54
  &-full-width {
55
55
  flex-direction: column;
56
+
57
+ &:has(.mw-actions-note),
58
+ &:has(.mw-form-actions-hint) {
59
+ flex-wrap: nowrap;
60
+ }
61
+
62
+ .mw-actions-note,
63
+ .mw-form-actions-hint {
64
+ flex: 0 0 auto;
65
+ text-align: left;
66
+ }
67
+
56
68
  > * {
57
69
  width: 100%;
58
70
  }
@@ -15,6 +15,10 @@
15
15
  flex-direction: column;
16
16
  align-items: stretch;
17
17
 
18
+ @include media-down('sm') {
19
+ width: min(340px, 100%);
20
+ }
21
+
18
22
  @include media-down('xs') {
19
23
  padding: spacing('7') spacing('4');
20
24
  }
@@ -81,16 +81,17 @@
81
81
 
82
82
  .mw-social-links {
83
83
  display: flex;
84
+ flex-wrap: wrap;
84
85
  justify-content: center;
85
86
  align-items: center;
86
87
  column-gap: spacing('8');
87
88
  row-gap: spacing('4');
88
89
  margin: spacing('6') auto;
89
90
 
90
- // modifier for more elements
91
+ // Modifier for more elements
91
92
  &.mod-wrap {
92
- flex-wrap: wrap;
93
93
  width: 510px;
94
+ max-width: 100%;
94
95
  }
95
96
 
96
97
  a {
@@ -162,7 +163,7 @@
162
163
  width: 330px;
163
164
  }
164
165
 
165
- button {
166
+ a {
166
167
  width: 40px;
167
168
  height: 40px;
168
169
  font-size: font-size('md');
@@ -191,19 +192,17 @@
191
192
  max-width: 100%;
192
193
  padding: spacing('0') spacing('4');
193
194
  }
194
-
195
- button {
196
- width: 33px;
197
- height: 33px;
198
- font-size: font-size('md');
199
- }
200
195
  }
201
196
 
197
+ // A second 15% inset inside a container that already keeps a gutter only
198
+ // narrows the line to no purpose
202
199
  .mw-disclaimer {
200
+ width: 100%;
203
201
  font-size: font-size('xs');
204
202
  }
205
203
 
206
204
  .mw-copyright {
205
+ width: 100%;
207
206
  margin-top: spacing('5');
208
207
  font-size: font-size('xs');
209
208
  }
@@ -29,6 +29,7 @@
29
29
  display: flex;
30
30
  justify-content: space-between;
31
31
  align-items: center;
32
+ gap: spacing('3');
32
33
  }
33
34
 
34
35
  .mw-logo {
@@ -36,17 +37,21 @@
36
37
  align-items: center;
37
38
  z-index: z-index('header') + 5;
38
39
  position: relative;
39
- flex-shrink: 0;
40
+ flex-shrink: 1;
41
+ min-width: 0;
40
42
 
41
43
  button {
42
44
  display: inline-block;
43
45
  text-decoration: none;
46
+ min-width: 0;
44
47
  }
45
48
 
46
49
  img {
47
50
  height: 42px;
48
51
  width: auto;
49
52
  max-width: 100%;
53
+ object-fit: contain;
54
+ object-position: left center;
50
55
  display: block;
51
56
  }
52
57
  }
@@ -55,6 +60,7 @@
55
60
  display: flex;
56
61
  align-items: center;
57
62
  gap: spacing('2');
63
+ flex-shrink: 0;
58
64
  }
59
65
 
60
66
  // Login button styling
@@ -13,10 +13,6 @@
13
13
  margin: spacing('0') auto;
14
14
  padding: spacing('0');
15
15
 
16
- @include media-down('sm') {
17
- width: var(--mw-container-width-sm);
18
- }
19
-
20
16
  // add a hero part for a full size background picture
21
17
  @supports (selector(:has(.mw-hero))) {
22
18
  // if it has *any* descendant .mw-hero
@@ -68,6 +64,14 @@
68
64
  // Pure CSS, no script needed. The flip side of that: it is a pseudo element on
69
65
  // the trigger, so an ancestor with `overflow: hidden` (a card, a scroll
70
66
  // container) cuts it off.
67
+ //
68
+ // Hidden means `display: none`, not `visibility: hidden`. A box that is hidden
69
+ // but still laid out counts towards the page's scrollable overflow: a 280px
70
+ // bubble centred on a trigger near the right edge added 50px of sideways scroll
71
+ // to a 320px screen, on a page where nothing visible was out of place. Coming
72
+ // back from `display: none` is a discrete transition, hence `allow-discrete`
73
+ // and the starting style - a browser that knows neither simply drops the
74
+ // transition and shows the bubble at once.
71
75
  $_mw-tooltip-arrow: 6px;
72
76
  $_mw-tooltip-gap: 8px;
73
77
 
@@ -91,8 +95,10 @@ $_mw-tooltip-gap: 8px;
91
95
  box-shadow: 0 2px 5px var(--mw-shadow);
92
96
  pointer-events: none;
93
97
  opacity: 0;
94
- visibility: hidden;
95
- transition: opacity 0.2s ease;
98
+ display: none;
99
+ transition:
100
+ opacity 0.2s ease,
101
+ display 0.2s allow-discrete;
96
102
  z-index: z-index('tooltip');
97
103
  }
98
104
 
@@ -107,8 +113,10 @@ $_mw-tooltip-gap: 8px;
107
113
  border-bottom-width: 0;
108
114
  border-top-color: var(--mw-gray-color);
109
115
  opacity: 0;
110
- visibility: hidden;
111
- transition: opacity 0.2s ease;
116
+ display: none;
117
+ transition:
118
+ opacity 0.2s ease,
119
+ display 0.2s allow-discrete;
112
120
  z-index: z-index('tooltip');
113
121
  }
114
122
 
@@ -117,7 +125,11 @@ $_mw-tooltip-gap: 8px;
117
125
  &:focus-visible::before,
118
126
  &:focus-visible::after {
119
127
  opacity: 1;
120
- visibility: visible;
128
+ display: block;
129
+
130
+ @starting-style {
131
+ opacity: 0;
132
+ }
121
133
  }
122
134
  }
123
135
 
@@ -98,8 +98,7 @@
98
98
  }
99
99
 
100
100
  .mw-section-btn {
101
- width: 90%;
102
- margin: spacing('0') auto;
101
+ width: 100%;
103
102
  text-align: center;
104
103
  }
105
104
  }
@@ -22,6 +22,18 @@
22
22
  min-height: 2.5rem;
23
23
  }
24
24
 
25
+ .mw-input,
26
+ .mw-input-sm,
27
+ .mw-input-lg,
28
+ .mw-select,
29
+ .mw-select-sm,
30
+ .mw-select-lg,
31
+ .mw-textarea,
32
+ .mw-textarea-sm,
33
+ .mw-textarea-lg {
34
+ font-size: 16px;
35
+ }
36
+
25
37
  // A tab strip is the one navigation a phone has no fallback for
26
38
  .mw-tabs-nav-item {
27
39
  display: flex;