maverick-wave 5.3.0 → 5.4.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.
@@ -44,14 +44,14 @@ Load the one you need - do not read them all up front.
44
44
  ```html
45
45
  <link
46
46
  rel="stylesheet"
47
- href="https://cdn.jsdelivr.net/npm/maverick-wave@5.2.0/maverick-wave.min.css"
47
+ href="https://cdn.jsdelivr.net/npm/maverick-wave@5.4.0/maverick-wave.min.css"
48
48
  />
49
49
  <link
50
50
  rel="stylesheet"
51
51
  href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
52
52
  />
53
53
  ...
54
- <script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.2.0/maverick-wave.min.js"></script>
54
+ <script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.4.0/maverick-wave.min.js"></script>
55
55
  ```
56
56
 
57
57
  Pin the version. The JS file is optional and only for server-rendered/static pages -
@@ -233,7 +233,8 @@ feature frame) ·
233
233
  `-highlight`, `-static`, color variants) · `mw-empty-state` ·
234
234
  `mw-spinner-border` / `mw-spinner-dots` / `mw-spinner-dual-ring` · `mw-skeleton`
235
235
 
236
- **Navigation** `mw-header` + `mw-navbar` · `mw-breadcrumbs` · `mw-pagination` ·
236
+ **Navigation** `mw-header` (+ `mw-header-reveal`) + `mw-navbar` ·
237
+ `mw-breadcrumbs` · `mw-pagination` ·
237
238
  `mw-dropdown` (+ `-menu`, `-item`, `-item-danger`, `-divider`, `-label`,
238
239
  `-caret`, `-end`, `-up`) · `mw-lang-switch` (+ `-code`, `-name`, `-check`,
239
240
  `inverted`) · `mw-flag` (+ 23 country codes) ·
@@ -252,7 +253,9 @@ feature frame) ·
252
253
 
253
254
  **Layout** (`references/layout.md`) `mw-main` · `mw-container` · `mw-content` ·
254
255
  `mw-section` (+ `mw-section-intro`) · `mw-page-header` · `mw-grid-*` ·
255
- `mw-columns-2/3` · `mw-row-split` · `mw-hero` (+ `mw-scroll-hint`, `-end`) · `mw-footer`
256
+ `mw-columns-2/3` · `mw-row-split` · `mw-hero` (+ `mw-scroll-hint`, `-end`) ·
257
+ `mw-parallax` (+ `-media`, `-content`, `-dimmed`, `-sticky`, `-rise`,
258
+ `-pattern`) · `mw-footer`
256
259
 
257
260
  **Utilities** (`references/layout.md`) `mw-sr-only` / `mw-sr-only-focusable` /
258
261
  `mw-skip-link` · `mw-row-split` (+ `center`) · `mw-text-numeric` /
@@ -403,3 +406,9 @@ feature frame) ·
403
406
  control height and works on an `<a>` and a `<button>` alike.
404
407
  `mw-btn mw-btn-link` stays right where the link really is one of several
405
408
  buttons and has to line up with them - a card's actions, a button bar.
409
+ 29. **`mw-parallax-sticky` goes on the section, not on the hero.** Sticky pins
410
+ inside its parent, and the rule that lifts the page above the pinned picture
411
+ reaches that content as a _sibling_. Put the class on the hero itself and
412
+ nothing pins and nothing covers - no error, no effect, and the picture shows
413
+ through every transparent section below. `mw-parallax` and the
414
+ `mw-parallax-media` child stay where the image is: on the container.
@@ -20,7 +20,7 @@ accordion FAQ.
20
20
 
21
21
  <link
22
22
  rel="stylesheet"
23
- href="https://cdn.jsdelivr.net/npm/maverick-wave@5.2.0/maverick-wave.min.css"
23
+ href="https://cdn.jsdelivr.net/npm/maverick-wave@5.4.0/maverick-wave.min.css"
24
24
  />
25
25
  <link
26
26
  rel="stylesheet"
@@ -487,7 +487,7 @@ accordion FAQ.
487
487
  <div class="mw-modal-backdrop" onclick="closeModal('demo')"></div>
488
488
  </div>
489
489
 
490
- <script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.2.0/maverick-wave.min.js"></script>
490
+ <script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.4.0/maverick-wave.min.js"></script>
491
491
  <script>
492
492
  // The only thing the shipped script does not cover: opening a modal.
493
493
  // Closing works through .mw-modal-close, the backdrop is wired above.
@@ -699,6 +699,10 @@ The height lives in `--mw-announcement-height` and drives the anchor scroll
699
699
  offset (`scroll-padding-top`) automatically - a taller ribbon raises the token
700
700
  instead of fighting the offset.
701
701
 
702
+ On a page whose header carries `mw-header-reveal` the ribbon leaves and arrives
703
+ with it, without a class of its own - both cover the height of the pair, so they
704
+ come in as one block. See `references/layout.md`.
705
+
702
706
  ## Empty state
703
707
 
704
708
  ```html
@@ -32,6 +32,7 @@ classes are the entire contract.
32
32
  | Modal | Click on `mw-modal-close` removes `mw-modal-open` from the overlay | `[class.mw-modal-open]="isOpen()"`; backdrop click closes. Opening is not in the script at all (the showcase has its own `openModal`) |
33
33
  | Mobile nav | Toggles `open` on `mw-menu-btn` and `mw-navbar`, writes `aria-expanded` when the button is a `<button>`, closes on anchor click and on Escape (focus returns to the button) | One signal, bound to both; reset it on navigation end |
34
34
  | Scroll spy | Sets `mw-active` on `mw-navbar-link` from the scroll position | Router-based: `routerLinkActive="mw-active"` |
35
+ | Anchor scrolling | Intercepts `a[href^="#"]` and runs its own eased scroll - duration scales with distance, capped at 1.4s, cancelled by wheel or touch. Lands on `scroll-padding-top`, moves focus to the target, writes the hash with `replaceState`, and measures a sticky target unpinned | The router; for in-page anchors `scrollIntoView({ behavior: 'smooth' })` or your own animation |
35
36
  | Theme toggle | `localStorage['mw-theme']`, toggles `mw-theme-light` on `<body>` and `mw-active` on the toggle, wrapped in `mw-theme-switching` on `<html>` so the flip starts no transitions | A theme service - see `examples/angular-services.md` |
36
37
  | Progress bar | `IntersectionObserver` sets `width` from `data-value` | Bind `[style.width.%]="value()"` on `mw-progress-fill` |
37
38
  | Slider | On `input`, sets `--value` (track fill) and `data-value` (badge text) | Bind `[style.--value.%]` and `[attr.data-value]` |
@@ -133,6 +133,18 @@ same height as the login and burger buttons.
133
133
  to configure dark-theme values to change it. The bar itself is the primary
134
134
  darkened toward black, `$header-surface` (14%) - see `theming.md`.
135
135
 
136
+ **Reveal on scroll.** `mw-header-reveal` keeps the bar above the screen and
137
+ rides it in over the first 420px of scroll - for a page that opens on a
138
+ full-bleed hero and wants nothing on top of it. It animates `top` and not a
139
+ transform, because a transform on the header would make it the containing block
140
+ of the off-canvas drawer inside it, at every value including the resting one.
141
+ A fixed `mw-announcement` rides along without a class of its own - both cover
142
+ the height of the pair, so they arrive as one block rather than the ribbon
143
+ catching up. Focus inside either brings both back regardless of the scroll
144
+ position, so tabbing never lands on a link that is off screen (WCAG 2.4.11).
145
+ Without scroll timelines, or under `prefers-reduced-motion`, the bar is simply
146
+ there.
147
+
136
148
  **Localhost indicator.** Put `mw-localhost-indicator-activated` on the header
137
149
  and the shipped JS prepends a pulsing bar when the host is localhost/127.0.0.1/
138
150
  192.168.\*. In a SPA, reimplement it: add a `<div class="mw-localhost-indicator-pulse">`
@@ -307,6 +319,59 @@ whose text is not centred either - and gives the hero its full height back.
307
319
  Below `md` both variants sit in the corner, because the middle under the text
308
320
  is taken on a phone. The bobbing stops under `prefers-reduced-motion`.
309
321
 
322
+ **Parallax** - `mw-parallax` on the container plus a `mw-parallax-media` child
323
+ moves the picture into its own layer. The container drops its own background and
324
+ the layer reads `--mw-hero-background`, so the image stays configured in one
325
+ place. Both modes run on the browser's scroll timeline - no listener, and no
326
+ `background-attachment: fixed`, which iOS ignores.
327
+
328
+ ```html
329
+ <header class="mw-header mw-header-reveal">...</header>
330
+
331
+ <main class="mw-main">
332
+ <section class="mw-section mw-parallax-sticky mw-parallax-rise">
333
+ <div class="mw-container mw-parallax">
334
+ <div class="mw-parallax-media"></div>
335
+ <div class="mw-parallax-media mw-parallax-pattern"></div>
336
+ <div class="mw-hero">...</div>
337
+ </div>
338
+ </section>
339
+ <section class="mw-section">...</section>
340
+ </main>
341
+ ```
342
+
343
+ On its own, `mw-parallax` drifts the picture against the scroll by
344
+ `--mw-parallax-depth` (`10vh`) - the layer overhangs the block by that much top
345
+ and bottom, so no edge is ever uncovered.
346
+
347
+ `mw-parallax-sticky` pins the block to the top of the screen and lets the page
348
+ ride up over it. It goes on the element the page content is a **sibling** of -
349
+ the section, not the hero - because everything after it is given
350
+ `--mw-page-background` and a layer above, or the pinned picture shows through
351
+ the transparent ones. Depth drops to `0` there: a pinned block does not travel
352
+ through the viewport, so its `view()` timeline stands still with it.
353
+ `mw-parallax-rise` puts it at `12vh` and runs the layer on the document's own
354
+ scroll instead - the picture lifts, the text stays put. That works out to the
355
+ same travel per scrolled pixel as a drifting band at `20vh`, which is measured
356
+ over a much longer range.
357
+
358
+ A second `mw-parallax-media` carrying `mw-parallax-pattern` puts a pattern over
359
+ the picture. It travels a third of the distance the layer below it does, and
360
+ that difference between the two is what reads as depth - one layer alone only
361
+ slides. It matters most over a gradient: the travel is vertical, so only an edge
362
+ across it - a rule, a grid, a hatch - ever shows the movement, and a gradient
363
+ has none. In a hero the layer reads `$mw-hero-pattern`, the way the picture
364
+ reads `$mw-hero-image`; anywhere else set `--mw-parallax-pattern-image` on it.
365
+ `--mw-parallax-pattern-depth` is the dial, `4vh` next to a risen hero.
366
+
367
+ Outside a hero the same classes build a standalone band: `mw-parallax`
368
+ (`min-height: 42vh`), `mw-parallax-media` as an `<img>` or a div with a
369
+ background image, `mw-parallax-content` for what sits on top, and
370
+ `mw-parallax-dimmed` to turn the picture down and the text light.
371
+
372
+ Without scroll timelines, or under `prefers-reduced-motion`, the picture stands
373
+ still and nothing else changes.
374
+
310
375
  ## Grid
311
376
 
312
377
  All grid classes are `display: grid` with a preset gap (`mw-gap-*` overrides
@@ -226,6 +226,12 @@ effect, because the root colours are declared with `!default`.
226
226
  // stronger, more saturated blue, higher is paler with more contrast
227
227
  $header-active-tint: 25%,
228
228
  $mw-hero-image: url('/assets/hero.jpg'),
229
+ // a pattern layer over it, for a hero that parallaxes - see mw-parallax-pattern
230
+ $mw-hero-pattern: repeating-linear-gradient(
231
+ to bottom,
232
+ rgb(255 255 255 / 5%) 0 1px,
233
+ transparent 1px 38px
234
+ ),
229
235
  // ink on that image - fixed, because the image is
230
236
  $mw-hero-text-color: var(--mw-dark-text-color),
231
237
  // per-theme treatment of that image - a filter, not an overlay, so the two
package/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@ 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
+ ## [5.4.0] - 2026-09-11
10
+
11
+ ### Added
12
+
13
+ - parallax layout
14
+ - parallax hero with flexible header navbar
15
+
9
16
  ## [5.3.0] - 2026-09-11
10
17
 
11
18
  ### Fixed
package/README.md CHANGED
@@ -42,12 +42,12 @@ The result is a framework that balances utility with simplicity, offering develo
42
42
  <title>My MaverickWave Project</title>
43
43
  <link
44
44
  rel="stylesheet"
45
- href="https://cdn.jsdelivr.net/npm/maverick-wave@5.2.0/maverick-wave.min.css"
45
+ href="https://cdn.jsdelivr.net/npm/maverick-wave@5.4.0/maverick-wave.min.css"
46
46
  />
47
47
  </head>
48
48
  <body>
49
49
  <!-- Your content here -->
50
- <script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.2.0/maverick-wave.min.js"></script>
50
+ <script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.4.0/maverick-wave.min.js"></script>
51
51
  </body>
52
52
  </html>
53
53
  ```
package/index.html CHANGED
@@ -69,6 +69,31 @@
69
69
  border: 1px solid var(--mw-border);
70
70
  }
71
71
 
72
+ /* The parallax pattern demo: a gradient has no edge across the travel,
73
+ the second layer brings one */
74
+ .parallax-demo-ground {
75
+ background-image: linear-gradient(
76
+ 158deg,
77
+ #3c4f78 0%,
78
+ #2a3550 45%,
79
+ #1b2334 100%
80
+ );
81
+ }
82
+
83
+ .parallax-demo-lines {
84
+ --mw-parallax-pattern-image:
85
+ repeating-linear-gradient(
86
+ to bottom,
87
+ rgb(255 255 255 / 24%) 0 1px,
88
+ transparent 1px 34px
89
+ ),
90
+ repeating-linear-gradient(
91
+ to right,
92
+ rgb(255 255 255 / 14%) 0 1px,
93
+ transparent 1px 34px
94
+ );
95
+ }
96
+
72
97
  /* A calendar fills its container; across the full page that stretches the
73
98
  cells to 150px, so the demos get a realistic column instead */
74
99
  .calendar-demo {
@@ -102,7 +127,7 @@
102
127
  <a class="mw-skip-link" href="#main">Skip to content</a>
103
128
 
104
129
  <!-- Header -->
105
- <header class="mw-header mw-localhost-indicator-activated">
130
+ <header class="mw-header mw-header-reveal mw-localhost-indicator-activated">
106
131
  <div class="mw-container">
107
132
  @@include('./src/partials/header-container.html')
108
133
  </div>
@@ -110,8 +135,8 @@
110
135
 
111
136
  <main class="mw-main" id="main">
112
137
  <!-- Home section -->
113
- <section id="home" class="mw-section">
114
- <div class="mw-container">
138
+ <section id="home" class="mw-section mw-parallax-sticky mw-parallax-rise">
139
+ <div class="mw-container mw-parallax">
115
140
  @@include('./src/partials/home-container.html')
116
141
  </div>
117
142
  </section>
@@ -210,6 +235,7 @@
210
235
  <a href="#html-lists" class="mw-section-btn">HTML Lists</a>
211
236
  <a href="#item-lists" class="mw-section-btn">Item Lists</a>
212
237
  <a href="#stepper" class="mw-section-btn">Stepper</a>
238
+ <a href="#parallax" class="mw-section-btn">Parallax</a>
213
239
  </nav>
214
240
 
215
241
  <!-- Grid container -->
@@ -258,6 +284,11 @@
258
284
  <div id="stepper">
259
285
  @@include('./src/partials/stepper-container.html')
260
286
  </div>
287
+
288
+ <!-- Parallax container -->
289
+ <div id="parallax">
290
+ @@include('./src/partials/parallax-container.html')
291
+ </div>
261
292
  </div>
262
293
  </section>
263
294