maverick-wave 4.6.0 → 4.8.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.
@@ -163,7 +163,8 @@ Everything below is documented in `references/components.md` unless marked other
163
163
  `link`, `link-muted`, `plain`, `sm`, `lg`) · `mw-btn-mini` · `mw-button-bar`
164
164
  (+ `left`, `right`, `center`, `between`) · `mw-segmented` · `mw-actions-note`
165
165
 
166
- **Containers** `mw-card` (+ `simple`, `lg`, `xl`, `stack`, badge, ribbon) ·
166
+ **Containers** `mw-card` (+ `simple`, `lg`, `xl`, `stack`, badge, ribbon,
167
+ feature frame) ·
167
168
  `mw-panel` · `mw-tile` · `mw-accordion` · `mw-tabs` · `mw-modal` ·
168
169
  `mw-item-list` family
169
170
 
@@ -149,13 +149,20 @@ picker.
149
149
  - `mw-card-simple` is the flat variant with even padding for arbitrary content.
150
150
  Use it when you only need a padded surface - it stays a block container, so
151
151
  inline children keep flowing side by side.
152
- - Image height: 210px, `mw-card-lg` 340px, `mw-card-xl` 480px. Set
153
- `--mw-card-img-height` on the card for any other height.
152
+ - Image height: 210px, `mw-card-lg` 340px, `mw-card-xl` 480px (260px/340px below
153
+ `sm`). Set `--mw-card-img-height` on the card for any other height.
154
154
  `mw-card-img-contain` shows the whole image instead of cropping it.
155
155
  - `mw-card-footer` pushes its last child to the right - with a single child that
156
156
  means it sits right, not left. Everything is vertically centered, so plain text
157
- lines up with a button next to it. Below `lg` the footer stacks and children go
158
- full width.
157
+ lines up with a button next to it. Actions that no longer fit next to each
158
+ other wrap.
159
+ - The footer stacks to full-width children once the **card** is narrower than
160
+ 360px, not once the window is - a card in a three-column grid is just as narrow
161
+ on a 1200px desktop as it is on a phone, and now looks the same in both. This
162
+ is a container query: a card that has a footer declares
163
+ `container: mw-card / inline-size` and takes `width: 100%`, so it fills its
164
+ slot instead of sizing to its content. Give such a card an explicit width if
165
+ you need it to hug its content.
159
166
  - `mw-card-badge` (top right corner) and `mw-card-ribbon` (diagonal banner) are
160
167
  absolutely positioned overlays; colour them with `mw-card-addon-primary`,
161
168
  `-secondary`, `-success`, `-warning`, `-danger`, `-info`.
@@ -172,6 +179,42 @@ picker.
172
179
  </div>
173
180
  ```
174
181
 
182
+ **Feature frame** - wraps a card to lift one option out of a grid of equals,
183
+ for the "most booked" plan in a pricing row:
184
+
185
+ ```html
186
+ <div class="mw-card-feature mw-card-feature-secondary">
187
+ <p class="mw-card-feature-label">Most booked</p>
188
+ <div class="mw-card">
189
+ <div class="mw-card-body">...</div>
190
+ </div>
191
+ </div>
192
+ ```
193
+
194
+ - Unlike badge and ribbon this is a **wrapper around** the card, not an overlay
195
+ inside it. The card itself stays untouched - same width, same height, same
196
+ hover as its neighbours - and the frame plus its label bar grow outwards into
197
+ the grid gap.
198
+ - Colours are `mw-card-feature-secondary` and `mw-card-feature-info`; primary is
199
+ the default and needs no class. This is a separate set from the
200
+ `mw-card-addon-*` classes that colour badge and ribbon - the frame only comes
201
+ in those three.
202
+ - The label is a single line. It is set in uppercase at `2xs` and truncates with
203
+ an ellipsis rather than wrapping, because the 22px bar height is baked into
204
+ the frame's negative margins.
205
+ - The frame reaches 29px above the card and 7px below it, so it sticks out of
206
+ its grid cell. Any `mw-grid-*` that directly contains one therefore gets
207
+ `row-gap: 56px` automatically, which leaves 20px between two stacked frames.
208
+ CSS has no per-row gap, so this applies to every row of that grid - expect
209
+ wrapped rows without a frame to sit further apart than usual. That is also why
210
+ the bar is kept low: each extra pixel is charged to every row.
211
+ - The space **above the first row** is not covered - the frame reaches into
212
+ whatever sits there. Give the container the room (`mw-mt-10` on the grid, or
213
+ `mw-mb-10` on the heading above it).
214
+ - In a layout that is not a `mw-grid-*` - your own flex column, an Angular host
215
+ with its own grid - nothing raises the gap for you. Leave at least 36px
216
+ between stacked items yourself.
217
+
175
218
  **Stack card** - icon + title header with a gradient rule, for feature or
176
219
  tech-stack grids:
177
220
 
@@ -25,12 +25,15 @@
25
25
 
26
26
  - `mw-main` is a full-height flex column - the footer stays at the bottom on
27
27
  short pages.
28
- - `mw-container` is `min(1200px, 89%)`, horizontally centered. Nest it inside
29
- every full-bleed band (header, section, footer), never around them. Below
30
- 576px it switches to a fixed 1rem gutter instead of the percentage - 89% of a
31
- 375px screen leaves 41px of nothing on a card that has to fit an amount, a
32
- status and two labels into one row. Both widths are tokens,
33
- `--mw-container-width` and `--mw-container-width-sm`.
28
+ - `mw-container` is `min(1200px, 100% - 2 * gutter)`, horizontally centered.
29
+ Nest it inside every full-bleed band (header, section, footer), never around
30
+ them. The gutter is fluid - `clamp(1rem, 4.2vw + 0.5rem, 4rem)`, never smaller
31
+ than the safe-area inset - so it lands on ~24px at 375px, ~32px at 576px,
32
+ ~40px on a tablet and tops out at 64px, where the 1200px cap takes over. A
33
+ percentage alone keeps too little on a phone and throws away too much on a
34
+ desktop; stepping the gutter at a breakpoint instead would make the container
35
+ jump backwards at the step. Both values are tokens,
36
+ `--mw-container-gutter` and `--mw-container-width`.
34
37
  - `mw-content` (`flex: 1` + top padding) is the alternative to `mw-section` when
35
38
  a page has one single content area. `mw-content-centered` centers it
36
39
  vertically over the full viewport - login pages, error pages.
@@ -68,22 +68,23 @@ Safari 16.4+, Firefox 128+.
68
68
  | `--mw-font-family-base`, `-heading`, `-mono` | Font stacks - system stacks by default (`-mono` leads with Fira Code); no font is bundled. Configurable in SCSS, see below |
69
69
  | `--mw-hero-background` | Hero image (`url(...)`) |
70
70
  | `--mw-transition` | Global transition (`all 0.3s ease`) |
71
- | `--mw-card-img-height` | Per-card image height (default `210px`; `mw-card-lg`/`-xl` set it to 340px/480px) |
71
+ | `--mw-card-img-height` | Per-card image height (default `210px`; `mw-card-lg`/`-xl` set it to 340px/480px, 260px/340px below `sm`) |
72
72
  | `--mw-card-addon-color` | Background of `mw-card-badge` / `mw-card-ribbon`; the `mw-card-addon-*` classes set it, override it for a custom colour |
73
73
  | `--mw-card-addon-text-color` | Label on that badge/ribbon; the `mw-card-addon-*` classes point it at the matching `--mw-*-accent-text-color` |
74
74
  | `--mw-progress-ink` | Label inside `mw-progress-inline-label`; the `mw-progress-*` colour classes point it at the matching `--mw-*-accent-text-color` |
75
75
  | `--mw-table-scroll-height` | Per-table height cap for `mw-table-responsive-scroll` |
76
76
  | `--mw-kanban-background`, `--mw-kanban-lane-border`, `--mw-kanban-column-min-height` | Per-board surface, lane border and lane floor (120px, 90px on `mw-kanban-compact`) |
77
- | `--mw-container-width`, `--mw-container-width-sm` | Content width of `mw-container` (`min(1200px, 89%)`, below 576px a 1rem gutter) |
77
+ | `--mw-container-gutter`, `--mw-container-width` | Page gutter of `mw-container` (fluid `clamp(1rem, 4.2vw + 0.5rem, 4rem)`, never below the safe-area inset) and the width derived from it (`min(1200px, 100% - 2 * gutter)`) |
78
78
  | `--mw-section-padding-block` | Top/bottom rhythm of `mw-section` (1.75rem) |
79
79
  | `--mw-calendar-dot` | Colour of a single calendar dot - set it per dot or per cell; the `mw-calendar-dot-*` classes are presets for it |
80
80
  | `--mw-scroll-hint-cover` | Colour the scroll hint on a tab bar fades into. Preset to the page, re-pointed to the card background inside `mw-card`, `mw-panel`, `mw-modal`, `mw-tile`, `mw-calendar` |
81
81
  | `--mw-internal-theme-mode` | Read-only: what `$mw-theme-mode` was compiled to |
82
82
 
83
- `--mw-container-width`, `--mw-container-width-sm` and
84
- `--mw-section-padding-block` are the knobs a good default cannot settle, because
85
- the right answer differs per project: what reads as generous on a landing page
86
- costs visible content in an application with a sticky header.
83
+ `--mw-container-gutter`, `--mw-container-width` and `--mw-section-padding-block`
84
+ are the knobs a good default cannot settle, because the right answer differs per
85
+ project: what reads as generous on a landing page costs visible content in an
86
+ application with a sticky header. Override the gutter, not the width - the width
87
+ is derived from it and keeps the 1200px cap.
87
88
 
88
89
  Two rules that prevent most colour bugs:
89
90
 
package/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ Patch releases are only for test purposes - here I only document major and minor
6
6
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [4.8.0] - 2026-08-22
10
+
11
+ ### Added
12
+
13
+ - `mw-card-feature` - frame with a label bar around a highlighted card, in primary, secondary and info
14
+
15
+ ## [4.7.0] - 2026-08-22
16
+
17
+ ### Changed
18
+
19
+ - mobile breakpoints view adjustments
20
+
9
21
  ## [4.6.0] - 2026-08-22
10
22
 
11
23
  ### Changed
package/gulpfile.js CHANGED
@@ -3,7 +3,18 @@ const fileinclude = require('gulp-file-include');
3
3
  const sass = require('gulp-sass')(require('sass'));
4
4
  const postcss = require('gulp-postcss');
5
5
  const autoprefixer = require('autoprefixer');
6
- const cleanCSS = require('gulp-clean-css');
6
+ // clean-css 4 is the last release gulp-clean-css pins, and it predates
7
+ // @container, @layer and @starting-style: it drops those blocks or eats their
8
+ // selectors without an error. cssnano runs in the postcss pass that is already
9
+ // here and understands them.
10
+ const cssnano = require('cssnano');
11
+ // postcss-calc cannot lex relative color syntax - `calc(l * 0.85)` inside
12
+ // `oklch(from ...)` makes it log a parse error per declaration. It leaves the
13
+ // value alone, so the output was always correct, but the noise buried real
14
+ // build errors. Switching it off leaves ten calc() terms unfolded
15
+ // (`calc(500px - 1.5rem - 2px)` stays as written), worth about 100 bytes across
16
+ // the whole file - cheaper than a build log nobody reads.
17
+ const cssnanoPreset = ['default', { calc: false }];
7
18
  const terser = require('gulp-terser');
8
19
  const fs = require('fs');
9
20
  const path = require('path');
@@ -47,8 +58,7 @@ gulp.task('scss-build', function () {
47
58
  return gulp
48
59
  .src(paths.scss)
49
60
  .pipe(sass().on('error', sass.logError))
50
- .pipe(postcss([autoprefixer()]))
51
- .pipe(cleanCSS())
61
+ .pipe(postcss([autoprefixer(), cssnano({ preset: cssnanoPreset })]))
52
62
  .pipe(rename('maverick-wave.min.css'))
53
63
  .pipe(gulp.dest(path.join(paths.dist)));
54
64
  });
@@ -56,8 +66,7 @@ gulp.task('scss-release', function () {
56
66
  return gulp
57
67
  .src(paths.scss)
58
68
  .pipe(sass().on('error', sass.logError))
59
- .pipe(postcss([autoprefixer()]))
60
- .pipe(cleanCSS())
69
+ .pipe(postcss([autoprefixer(), cssnano({ preset: cssnanoPreset })]))
61
70
  .pipe(rename('maverick-wave.min.css'))
62
71
  .pipe(gulp.dest(path.join(paths.root)));
63
72
  });
package/index.html CHANGED
@@ -94,8 +94,13 @@
94
94
 
95
95
  /* Small screens */
96
96
  @media (max-width: 576px) {
97
+ /* The h1 drops to 2.2rem down here, so the sticker has to move up with
98
+ it or it lands on the word instead of next to it */
97
99
  .version-corner {
100
+ top: -32px;
98
101
  right: 4%;
102
+ font-size: 0.9rem;
103
+ padding: 0.25rem 0.55rem;
99
104
  }
100
105
 
101
106
  .color-swatch {