maverick-wave 5.28.0 → 5.29.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/.claude/skills/mw-maverick-wave/SKILL.md +4 -2
- package/.claude/skills/mw-maverick-wave/references/components.md +212 -0
- package/.claude/skills/mw-maverick-wave/references/javascript.md +6 -1
- package/.claude/skills/mw-maverick-wave/references/theming.md +53 -51
- package/CHANGELOG.md +10 -0
- package/CLAUDE.md +4 -4
- package/README.md +2 -2
- package/index.html +65 -0
- package/maverick-wave.min.css +2 -2
- package/maverick-wave.min.js +1 -1
- package/package.json +2 -2
- package/scripts/verify.js +2 -1
- package/src/assets/images/photo-balloon.svg +35 -0
- package/src/assets/images/photo-forest-path.svg +31 -0
- package/src/assets/images/photo-lighthouse.svg +42 -0
- package/src/assets/images/photo-palm.svg +27 -0
- package/src/assets/images/photo-peak.svg +27 -0
- package/src/assets/images/photo-tower.svg +34 -0
- package/src/assets/images/photo-waterfall.svg +32 -0
- package/src/assets/images/story-aurora.svg +36 -0
- package/src/assets/images/story-beach.svg +34 -0
- package/src/assets/images/story-stars.svg +35 -0
- package/src/assets/media/story-sunrise.jpg +0 -0
- package/src/assets/media/story-sunrise.mp4 +0 -0
- package/src/js/main.js +403 -0
- package/src/partials/avatars-container.html +50 -0
- package/src/partials/calendar-container.html +36 -38
- package/src/partials/feed-container.html +506 -0
- package/src/partials/item-lists-container.html +80 -130
- package/src/partials/kanban-container.html +17 -294
- package/src/partials/mosaic-container.html +173 -0
- package/src/partials/panels-container.html +113 -162
- package/src/partials/portrait-gallery-container.html +175 -0
- package/src/partials/stories-container.html +182 -0
- package/src/partials/tables-container.html +21 -40
- package/src/scss/abstracts/_mixins.scss +2 -0
- package/src/scss/abstracts/_variables.scss +3 -0
- package/src/scss/components/_avatars.scss +52 -0
- package/src/scss/components/_cards.scss +7 -3
- package/src/scss/components/_feed.scss +203 -0
- package/src/scss/components/_index.scss +6 -0
- package/src/scss/components/_lightbox.scss +178 -0
- package/src/scss/components/_mosaic.scss +83 -0
- package/src/scss/components/_overlay-btn.scss +47 -0
- package/src/scss/components/_portrait-gallery.scss +180 -0
- package/src/scss/components/_stories.scss +443 -0
- package/src/scss/components/_tiles.scss +4 -1
- package/src/scss/utilities/_fit.scss +29 -0
- package/src/scss/utilities/_index.scss +1 -0
|
@@ -309,8 +309,10 @@ feature frame) ·
|
|
|
309
309
|
`inverted`) · `mw-flag` (+ 23 country codes) ·
|
|
310
310
|
`mw-section-nav` (`references/layout.md`)
|
|
311
311
|
|
|
312
|
-
**Media & content** `mw-avatar` (+ `initials`, `group
|
|
313
|
-
`mw-
|
|
312
|
+
**Media & content** `mw-avatar` (+ `initials`, `group`, `landscape`,
|
|
313
|
+
`portrait`) · `mw-gallery` · `mw-image-slider` · `mw-mosaic` (+ lightbox) ·
|
|
314
|
+
`mw-portrait-gallery` · `mw-feed` · `mw-stories` / `mw-story-reel` ·
|
|
315
|
+
`mw-overlay-btn` · `mw-blog-post` · `mw-testimonial` (+ `-source`, `-detail`,
|
|
314
316
|
`-date`, `-featured`) · `mw-prose` · `mw-media` (+ `-caption`) · `mw-code-block` /
|
|
315
317
|
`mw-terminal` · `mw-techstack-bucket` · `mw-coming-soon` · `mw-divider` ·
|
|
316
318
|
`mw-kbd` · `mw-list` family
|
|
@@ -1473,6 +1473,13 @@ deprecated). Any card fits into the content wrapper.
|
|
|
1473
1473
|
|
|
1474
1474
|
- Sizes: `mw-avatar-xs` 32, `-sm` 64, default 96, `-lg` 144, `-xl` 210 px.
|
|
1475
1475
|
- Shape: `mw-avatar-square`.
|
|
1476
|
+
- `mw-avatar-landscape` (3:2) and `mw-avatar-portrait` (9:16) for a photo that
|
|
1477
|
+
is not square - meant for `-lg` and `-xl`, with 20px corners that
|
|
1478
|
+
`mw-avatar-square` still sharpens. A landscape avatar keeps the height of its
|
|
1479
|
+
size step, a portrait one the width; on `-lg` a portrait is 2:3 instead, as
|
|
1480
|
+
tall as the 9:16 one and wider.
|
|
1481
|
+
- Every avatar carries the accent arc on its top-right corner, inside the frame
|
|
1482
|
+
(`--mw-corner-accent`). It stays as it is on hover.
|
|
1476
1483
|
- Colours `mw-avatar-primary`, `-secondary`, `-success`, `-warning`, `-danger`,
|
|
1477
1484
|
`-info` tint the **border**. On `mw-avatar-initials` the same class also tints
|
|
1478
1485
|
the **surface**, so both can be combined.
|
|
@@ -1802,6 +1809,211 @@ current button carry `active`. `mw-image-slider` is its own query container
|
|
|
1802
1809
|
switch at 420px and 560px of slider width, because the slider caps at 600px and
|
|
1803
1810
|
past a tablet the viewport says nothing about the room it has.
|
|
1804
1811
|
|
|
1812
|
+
## Mosaic
|
|
1813
|
+
|
|
1814
|
+
Photos of any shape in one grid; a tap opens the lightbox.
|
|
1815
|
+
|
|
1816
|
+
```html
|
|
1817
|
+
<div class="mw-mosaic">
|
|
1818
|
+
<figure class="mw-mosaic-item mw-mosaic-big">
|
|
1819
|
+
<a href="ridge-full.jpg">
|
|
1820
|
+
<img
|
|
1821
|
+
src="ridge.jpg"
|
|
1822
|
+
alt="Mountain range at sunrise"
|
|
1823
|
+
width="800"
|
|
1824
|
+
height="450"
|
|
1825
|
+
loading="lazy"
|
|
1826
|
+
/>
|
|
1827
|
+
</a>
|
|
1828
|
+
<figcaption>First light on the ridge.</figcaption>
|
|
1829
|
+
</figure>
|
|
1830
|
+
<figure class="mw-mosaic-item">…</figure>
|
|
1831
|
+
</div>
|
|
1832
|
+
```
|
|
1833
|
+
|
|
1834
|
+
- Two columns on a phone, four at most, from the width of the box it sits in.
|
|
1835
|
+
- The script shapes each tile from the photo's proportions - the `width` and
|
|
1836
|
+
`height` attributes, else the natural size once loaded: `mw-mosaic-wide` from
|
|
1837
|
+
1.3:1, `mw-mosaic-tall` from 1:1.25, square otherwise. A shape class set by
|
|
1838
|
+
hand wins; `mw-mosaic-big` (2×2) is only ever set by hand. Without the script
|
|
1839
|
+
every tile is square.
|
|
1840
|
+
- `grid-auto-flow: dense` fills the holes and moves tiles away from their source
|
|
1841
|
+
order. `reading-flow: grid-rows` makes Tab follow the eye where the browser
|
|
1842
|
+
has it (Chromium so far).
|
|
1843
|
+
- Gaps: `mw-mosaic-gap-sm`, `-gap-lg`.
|
|
1844
|
+
- The tile crops, the lightbox does not. The `figcaption` is hidden in the tile
|
|
1845
|
+
and shown in the lightbox.
|
|
1846
|
+
|
|
1847
|
+
### Lightbox
|
|
1848
|
+
|
|
1849
|
+
A click on a link that holds an image - inside `mw-mosaic` or any element with
|
|
1850
|
+
`data-mw-lightbox` - opens the photo full screen instead of following the link.
|
|
1851
|
+
The script builds the viewer once, a `<dialog class="mw-lightbox">`, with one
|
|
1852
|
+
slide per image of the group in reading order, the full image from the link's
|
|
1853
|
+
`href` and the caption copied from the `figcaption`. Swipe, arrow keys or the
|
|
1854
|
+
arrows page through it; Escape, the cross or a click on the stage beside the
|
|
1855
|
+
photo close it, and focus returns to the tile of the last photo viewed. A click
|
|
1856
|
+
with a modifier key stays a link.
|
|
1857
|
+
|
|
1858
|
+
Without `main.js`, build it yourself: a `<dialog class="mw-lightbox">` holding
|
|
1859
|
+
`mw-lightbox-bar` (with `mw-lightbox-prev`, `mw-lightbox-count`,
|
|
1860
|
+
`mw-lightbox-next` and `mw-lightbox-close`, all `mw-overlay-btn`) and
|
|
1861
|
+
`mw-lightbox-track` with one `<figure class="mw-lightbox-slide">` per photo. The
|
|
1862
|
+
track is a scroll-snap strip; the page scroll is locked while the dialog is open.
|
|
1863
|
+
|
|
1864
|
+
## Portrait gallery
|
|
1865
|
+
|
|
1866
|
+
```html
|
|
1867
|
+
<div class="mw-portrait-gallery">
|
|
1868
|
+
<div
|
|
1869
|
+
class="mw-portrait-gallery-track"
|
|
1870
|
+
tabindex="0"
|
|
1871
|
+
aria-label="Portrait photos"
|
|
1872
|
+
>
|
|
1873
|
+
<figure class="mw-portrait-gallery-slide">
|
|
1874
|
+
<img
|
|
1875
|
+
src="cape.jpg"
|
|
1876
|
+
alt="Lighthouse on a cliff at dusk"
|
|
1877
|
+
width="600"
|
|
1878
|
+
height="800"
|
|
1879
|
+
loading="lazy"
|
|
1880
|
+
/>
|
|
1881
|
+
<figcaption>
|
|
1882
|
+
<strong>North Cape</strong>
|
|
1883
|
+
The lamp comes on just after the sun goes.
|
|
1884
|
+
</figcaption>
|
|
1885
|
+
</figure>
|
|
1886
|
+
</div>
|
|
1887
|
+
</div>
|
|
1888
|
+
```
|
|
1889
|
+
|
|
1890
|
+
- Upright 3:4 slides in a native scroll-snap strip, the next one peeking in.
|
|
1891
|
+
One slide below 560px of gallery width, two and a quarter from there, three
|
|
1892
|
+
from 880px - a container query, so a gallery in a narrow column stays at one.
|
|
1893
|
+
The height is capped at 78svh, which a landscape phone needs.
|
|
1894
|
+
- `mw-portrait-gallery-tall`: 9:16, for stories, reels and screenshots. A
|
|
1895
|
+
`<video>` works in place of an `<img>`.
|
|
1896
|
+
- Gaps: `mw-portrait-gallery-gap-sm`, `-gap-lg`.
|
|
1897
|
+
- The script adds the arrows (`mw-portrait-gallery-prev` / `-next`, for a mouse
|
|
1898
|
+
only) and the dots (`mw-portrait-gallery-dots` / `-dot`, below 560px, the
|
|
1899
|
+
current one `mw-active`).
|
|
1900
|
+
- A photo more than 1.4× off the slide's shape is shown whole over a blurred
|
|
1901
|
+
copy of itself instead of cropped: the script sets `mw-fit-contain` on the
|
|
1902
|
+
slide and prepends a `mw-fit-backdrop` image, and checks again on every
|
|
1903
|
+
resize. `mw-fit-contain` set by hand forces it, `mw-fit-cover` on the slide
|
|
1904
|
+
turns it off.
|
|
1905
|
+
|
|
1906
|
+
## Photo feed
|
|
1907
|
+
|
|
1908
|
+
The three-column grid from a phone's photo app, in a framed box that scrolls.
|
|
1909
|
+
|
|
1910
|
+
```html
|
|
1911
|
+
<div class="mw-feed">
|
|
1912
|
+
<div class="mw-feed-item">
|
|
1913
|
+
<button type="button" popovertarget="post-cape">
|
|
1914
|
+
<img
|
|
1915
|
+
src="cape.jpg"
|
|
1916
|
+
alt="Lighthouse on a cliff at dusk"
|
|
1917
|
+
width="600"
|
|
1918
|
+
height="800"
|
|
1919
|
+
loading="lazy"
|
|
1920
|
+
/>
|
|
1921
|
+
</button>
|
|
1922
|
+
<figure class="mw-feed-post" id="post-cape" popover>
|
|
1923
|
+
<button
|
|
1924
|
+
type="button"
|
|
1925
|
+
class="mw-overlay-btn mw-feed-post-close"
|
|
1926
|
+
popovertarget="post-cape"
|
|
1927
|
+
popovertargetaction="hide"
|
|
1928
|
+
aria-label="Close"
|
|
1929
|
+
>
|
|
1930
|
+
𝗫
|
|
1931
|
+
</button>
|
|
1932
|
+
<img
|
|
1933
|
+
src="cape.jpg"
|
|
1934
|
+
alt="Lighthouse on a cliff at dusk"
|
|
1935
|
+
width="600"
|
|
1936
|
+
height="800"
|
|
1937
|
+
loading="lazy"
|
|
1938
|
+
/>
|
|
1939
|
+
<figcaption>
|
|
1940
|
+
<p>Stood there until the lamp came on.</p>
|
|
1941
|
+
<time datetime="2026-08-12">12 August 2026</time>
|
|
1942
|
+
</figcaption>
|
|
1943
|
+
</figure>
|
|
1944
|
+
</div>
|
|
1945
|
+
</div>
|
|
1946
|
+
```
|
|
1947
|
+
|
|
1948
|
+
- 3:4 tiles, 2px apart; `mw-feed-square` for square ones.
|
|
1949
|
+
- Past three rows the box scrolls, with a strip of the next row in view so it
|
|
1950
|
+
reads as scrollable. `mw-feed-rows-2` shows two rows, `mw-feed-plain` drops
|
|
1951
|
+
the frame.
|
|
1952
|
+
- No script: the tile is a button with `popovertarget`, the post a `popover`.
|
|
1953
|
+
In Angular that is `[attr.popovertarget]` and a matching `[id]`. A tile can be
|
|
1954
|
+
an `<a>` to a page of its own instead.
|
|
1955
|
+
- `time` and `small` in the caption are set as a muted line. The page scroll is
|
|
1956
|
+
locked while a post is open.
|
|
1957
|
+
|
|
1958
|
+
## Story archive
|
|
1959
|
+
|
|
1960
|
+
```html
|
|
1961
|
+
<div class="mw-stories" aria-label="Story archive">
|
|
1962
|
+
<button type="button" class="mw-story" popovertarget="story-coast">
|
|
1963
|
+
<span class="mw-story-cover"><img src="beach.jpg" alt="" /></span>
|
|
1964
|
+
<span class="mw-story-label">Coast</span>
|
|
1965
|
+
</button>
|
|
1966
|
+
<div class="mw-story-reel" id="story-coast" popover>
|
|
1967
|
+
<div class="mw-story-reel-head">
|
|
1968
|
+
<span>Coast</span>
|
|
1969
|
+
<label class="mw-overlay-btn mw-story-reel-pause"
|
|
1970
|
+
><input type="checkbox" aria-label="Pause"
|
|
1971
|
+
/></label>
|
|
1972
|
+
<button
|
|
1973
|
+
type="button"
|
|
1974
|
+
class="mw-overlay-btn"
|
|
1975
|
+
popovertarget="story-coast"
|
|
1976
|
+
popovertargetaction="hide"
|
|
1977
|
+
aria-label="Close"
|
|
1978
|
+
>
|
|
1979
|
+
𝗫
|
|
1980
|
+
</button>
|
|
1981
|
+
</div>
|
|
1982
|
+
<img src="beach.jpg" alt="Beach at sunset" loading="lazy" />
|
|
1983
|
+
<video
|
|
1984
|
+
src="sunrise.mp4"
|
|
1985
|
+
poster="sunrise.jpg"
|
|
1986
|
+
autoplay
|
|
1987
|
+
muted
|
|
1988
|
+
loop
|
|
1989
|
+
playsinline
|
|
1990
|
+
></video>
|
|
1991
|
+
</div>
|
|
1992
|
+
</div>
|
|
1993
|
+
```
|
|
1994
|
+
|
|
1995
|
+
- The row scrolls sideways, with a shadow on the side that has more behind it;
|
|
1996
|
+
a mouse gets a thin scrollbar.
|
|
1997
|
+
- Playback is CSS: every frame shows for five seconds, a segmented bar in the
|
|
1998
|
+
head counts them off, and holding the story (`:active`) or ticking the pause
|
|
1999
|
+
checkbox stops it. Full screen on a phone, phone-shaped (9:16) from `sm` up.
|
|
2000
|
+
- Twelve frames at most - the timing is written out for twelve. Later frames
|
|
2001
|
+
are hidden and the story ends after the twelfth.
|
|
2002
|
+
- Under `prefers-reduced-motion` nothing plays: the frames become a vertical
|
|
2003
|
+
strip to swipe, and the bar follows the scroll where the browser has scroll
|
|
2004
|
+
timelines.
|
|
2005
|
+
- The script adds tap zones (`mw-story-reel-prev` on the left 30%, `-next` on
|
|
2006
|
+
the rest), arrow keys, focus on the close button when the story opens, a video
|
|
2007
|
+
that starts when its frame comes up and stops with the story, and closes the
|
|
2008
|
+
story at its end.
|
|
2009
|
+
|
|
2010
|
+
## Overlay button
|
|
2011
|
+
|
|
2012
|
+
`mw-overlay-btn` is the round 44px button that sits on a photo - dark and
|
|
2013
|
+
translucent in both themes, with light ink and an inline `<svg>` sized for it.
|
|
2014
|
+
`:disabled` hides it. The lightbox, the portrait gallery, the feed post and the
|
|
2015
|
+
story reel use it for their close and arrow buttons.
|
|
2016
|
+
|
|
1805
2017
|
## Blog post
|
|
1806
2018
|
|
|
1807
2019
|
```html
|
|
@@ -76,6 +76,10 @@ its own through `light-dark()`.
|
|
|
76
76
|
| Checkbox lists | Adds `mw-selected` to the `li`, emits a `checkboxToggle` event, exposes `window.mwToggleCheckbox` | `[class.mw-selected]="item.checked"` |
|
|
77
77
|
| Gallery | Generates the dots, moves the track, swipe handling (single finger, dominant axis, passive listeners), writes `mw-gallery-desc` | Render dots in the template, bind the track transform and `mw-active` on the current dot |
|
|
78
78
|
| Image slider | Toggles `mw-active` on the overlay image and the control button with the matching `data-index` | Bind `mw-active` from the selected index |
|
|
79
|
+
| Mosaic | Sets `mw-mosaic-wide` / `mw-mosaic-tall` on a tile from the photo's proportions - its `width`/`height` attributes, else the natural size - unless a shape class is already there | Bind the shape class from the image size you already know |
|
|
80
|
+
| Lightbox | Delegated: an image link inside `mw-mosaic` or `[data-mw-lightbox]` opens a `<dialog class="mw-lightbox">` built once - slides in reading order, images loaded one either side of the current, swipe, arrows and keys, focus back on the tile of the last photo | A component around a `<dialog>`: `showModal()`, a scroll-snap track, the index read from `scrollLeft` |
|
|
81
|
+
| Portrait gallery | Adds arrows and dots and keeps them in step with the scroll position; sets `mw-fit-contain` and a blurred `mw-fit-backdrop` on a slide whose photo is more than 1.4× off its shape, checked again by a `ResizeObserver` | Render arrows and dots, `scrollBy` one slide on click; bind `mw-fit-contain` from the image ratio |
|
|
82
|
+
| Story reel | Playback is CSS. Adds the `mw-story-reel-prev` / `-next` tap zones and arrow keys (seeking through `getAnimations()`), starts a video when its frame comes up and stops it with the story, closes the popover at the end, focuses the close button on open | Keep the CSS playback and the popover; add stepping only if you need it, the same way |
|
|
79
83
|
| Kanban board | Counts the tickets per lane, moves a card between lanes (`data-kanban-move`) and marks the arrival with `mw-kanban-card-moved-forward` / `-back`, clones `mw-kanban-card-template` on save, derives the next key from `data-kanban-prefix`, toggles `mw-active` on the composer | Keep the tickets in a signal/store and render the lanes from it; `mw-active` on the composer, `mw-kanban-editing` on the ticket it replaces. Neither the `<template>` nor the `mw-kanban-composer-*` hook classes are needed |
|
|
80
84
|
| Calendar | Renders the month or week grid from `data-calendar="month | week"`, pages with `data-calendar-nav`, draws the status dots from `data-calendar-markers`, toggles `mw-selected`and emits`mw-calendar-select` | Render the cells from a signal and bind `mw-calendar-adjacent`, `mw-calendar-weekend`, `mw-calendar-today` and `mw-selected` yourself; none of the `data-calendar-*` attributes are needed |
|
|
81
85
|
| Viewport check | On a local hostname, warns on the console when the viewport meta has no `viewport-fit=cover` - without it every `env(safe-area-inset-*)` resolves to 0 | Nothing - check the meta tag once |
|
|
@@ -130,7 +134,8 @@ Pure CSS, nothing to wire up: hover, focus and press states, the card lift,
|
|
|
130
134
|
tooltips (`data-tooltip`), `mw-rating` (via `data-rating`), the responsive table
|
|
131
135
|
card view (`data-label`), all grids and utilities, the body scroll lock while a
|
|
132
136
|
modal is open (from the `<dialog>` element, or `body:has(.mw-modal-open)` for an
|
|
133
|
-
overlay div), the modal turning into a bottom sheet below 576px, toast entry animations, the
|
|
137
|
+
overlay div), the modal turning into a bottom sheet below 576px, toast entry animations, the photo feed and its post cards (`popover`), story
|
|
138
|
+
playback with its progress bar and pause, the sticky table header, the scroll
|
|
134
139
|
hint on a tab bar (four gradients, no scroll listener), the kanban empty-lane
|
|
135
140
|
placeholder (hidden via `:has()` as soon as the lane holds a ticket), touch
|
|
136
141
|
target sizing on a coarse pointer, `prefers-reduced-motion` handling.
|
|
@@ -50,56 +50,56 @@ Safari 16.4+, Firefox 128+. The same range is declared as `browserslist` in
|
|
|
50
50
|
|
|
51
51
|
## Which token for what
|
|
52
52
|
|
|
53
|
-
| Token | Role
|
|
54
|
-
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
55
|
-
| `--mw-primary-color` | Brand colour as a **fill**: primary buttons, table headers, bars, badges - the label on top is `--mw-primary-accent-text-color`
|
|
56
|
-
| `--mw-primary-text-color` | Brand colour as **ink** on a theme surface: text, icons, focus rings, accent borders. Derived by clamping OKLch lightness (`max(l, .68)` on dark, `min(l, .55)` on light), so a colour already in range is used untouched
|
|
57
|
-
| `--mw-primary-color-hover` | Solid hover surface (derived: base + `$hover-shift` black, in both themes)
|
|
58
|
-
| `--mw-primary-background` | 20% tint - focus halo, alert/badge/tag surface, scrollbar tracks
|
|
59
|
-
| `--mw-primary-background-hover` | 45% tint - row and list hover
|
|
60
|
-
| `--mw-primary-info-background` | Alias of `--mw-primary-background`, so a component can interpolate one name across all six colours
|
|
61
|
-
| `--mw-border-accent` | Translucent accent **line**: panel rules, dividers, tab underlines. Theme-aware (70% of `--mw-*-text-color`)
|
|
62
|
-
| `--mw-secondary-*` | Same set for the second brand colour
|
|
63
|
-
| `--mw-success/warning/danger/info-color` | Status colours, each with `-text-color`, `-color-hover`, `-info-background`, `-info-background-hover`
|
|
64
|
-
| `--mw-accent-text-color` | Text on any solid coloured surface (buttons, table/panel headers, badges, stepper dots)
|
|
65
|
-
| `--mw-primary-accent-text-color` | Per colour override of that label. Same for `secondary`, `success`, `warning`, `danger`, `info`. Defaults to `--mw-accent-text-color`, so set one only when a colour needs the opposite label - a neon primary on a dark palette
|
|
66
|
-
| `--mw-gray-color` | Neutral foreground: muted icons, tooltips
|
|
67
|
-
| `--mw-gray-background` | Subtle neutral surface (20% alpha): zebra rows, disabled fields, tracks, skeletons
|
|
68
|
-
| `--mw-corner-accent` | The accent arc on the two round corners of every card, panel, modal and tile. Theme-aware: the full `--mw-*-text-color` tone in the dark theme, held to 80% in the light one, where the same blue carries far more contrast on a near-white card. Restyle it to recolour the signature, or `mw-corner-plain` on a single box to drop it |
|
|
69
|
-
| `--mw-surface-muted` | Alias of `--mw-gray-background` under the name you reach for: a slightly set-off area _inside_ a card - hint block, framed paragraph, form summary
|
|
70
|
-
| `--mw-overlay-background` | Heavy scrim (60%) behind modals and blocking spinners
|
|
71
|
-
| `--mw-page-background`, `--mw-card-background`, `--mw-footer-background`, `--mw-border`, `--mw-shadow`, `--mw-text-color`, `--mw-text-muted-color`, `--mw-hero-image-filter` | The **active theme** - aliases pointing at the `--mw-dark-*` or `--mw-light-*` set
|
|
72
|
-
| `--mw-header-*` | Header chrome: `background`, `text-color`, `navbar-list-color`, `navbar-list-active-color`, `burgerbutton-color`, `burgerbutton-open-color`, `border` - dark in both themes. The two burger tokens default to the primary and secondary label ink, because the burger sits on those two surfaces
|
|
73
|
-
| `--mw-form-elements-background`, `--mw-form-elements-color` | Form controls stay light in both themes and therefore have their own pair
|
|
74
|
-
| `--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
|
|
75
|
-
| `--mw-hero-background`, `--mw-hero-text-color` | Hero image (`url(...)`) and the ink on it. Fixed across themes - the photo does not change with the theme, so its text must not either. Defaults to the light end of the palette
|
|
76
|
-
| `--mw-transition` | Hover and focus states - an explicit paint-only property list at `--mw-duration-base`, never `all`
|
|
77
|
-
| `--mw-card-img-height` | Per-card image height (default `210px`; `mw-card-lg`/`-xl` set it to 340px/480px, 260px/340px below `sm`)
|
|
78
|
-
| `--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
|
|
79
|
-
| `--mw-card-addon-text-color` | Label on that badge/ribbon; the `mw-card-addon-*` classes point it at the matching `--mw-*-accent-text-color`
|
|
80
|
-
| `--mw-progress-ink` | Label inside `mw-progress-inline-label`; the `mw-progress-*` colour classes point it at the matching `--mw-*-accent-text-color`
|
|
81
|
-
| `--mw-table-scroll-height` | Per-table height cap for `mw-table-responsive-scroll`
|
|
82
|
-
| `--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`)
|
|
83
|
-
| `--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)`)
|
|
84
|
-
| `--mw-section-padding-block` | Top/bottom rhythm of `mw-section` (3.3rem, stepping down to 2.5rem below `md` and 1.75rem below `sm`)
|
|
85
|
-
| `--mw-section-padding-fluid` | The fluid alternative to the value above - 1.75rem on a phone up to 5.5rem at `xl`. Not applied by itself: set `--mw-section-padding-block: var(--mw-section-padding-fluid)`
|
|
86
|
-
| `--mw-section-padding-compact`, `--mw-section-padding-airy` | The two presets, as tokens so the phone steps reach them - point `--mw-section-padding-block` at one
|
|
87
|
-
| `--mw-section-head-step` | One step of the head rhythm, derived from `--mw-section-padding-block`. Every measure in a head and around a subtitle is a multiple of it, so a spacing preset moves them all
|
|
88
|
-
| `--mw-section-nav-height` | Height the sticky `mw-section-nav` reserves (3.75rem). A page carrying a strip adds it to `scroll-padding-top` itself, through the offset token below
|
|
89
|
-
| `--mw-announcement-offset`, `--mw-section-nav-offset` | What each layer of sticky chrome below the header adds to `scroll-padding-top`. `0px` until the component switches it on, so a page with both a ribbon and a strip reserves for both. For a sticky bar of your own, override `scroll-padding-top` on `html` - the calc names these two
|
|
90
|
-
| `--mw-root-font-size` | Percentage the whole rem scale is built on (`100%`). Type, spacing and control heights move with it; px breakpoints do not
|
|
91
|
-
| `--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
|
|
92
|
-
| `--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`
|
|
93
|
-
| `--mw-elevation-1` … `-5` | Every shadow in the framework. Two layers per level - contact plus ambient. Never write a `box-shadow` by hand: a hand-rolled one is the wrong colour in one of the two themes
|
|
94
|
-
| `--mw-shadow-near`, `--mw-shadow-far` | The two tones the ramp above is mixed from, per theme
|
|
95
|
-
| `--mw-transition-fast` | The same property list at `--mw-duration-fast` - for a state change that should feel instant under the pointer
|
|
96
|
-
| `--mw-duration-instant\|fast\|base\|slow\|slower` | 110 / 180 / 300 / 520 / 900ms. Anything built on these is covered by `prefers-reduced-motion` for free
|
|
97
|
-
| `--mw-duration-zoom` | 650ms, for a large surface actually travelling - an image scaling inside a card, a slider track
|
|
98
|
-
| `--mw-ease-out`, `--mw-ease-in-out`, `--mw-ease-spring` | Things arriving (the default) / A to B and back / a pop
|
|
99
|
-
| `--mw-control-height-sm\|·\|lg`, `--mw-control-font-sm\|·\|lg`, `--mw-control-line-height` | One size scale for input, select, textarea and button, so a field and the button beside it line up by construction
|
|
100
|
-
| `--mw-focus-ring-width\|offset\|color` | The keyboard focus ring
|
|
101
|
-
| `--mw-focus-halo-size\|opacity` | The soft ring a form field gets instead of a hard outline
|
|
102
|
-
| `--mw-internal-theme-mode` | Read-only: what `$mw-theme-mode` was compiled to
|
|
53
|
+
| Token | Role |
|
|
54
|
+
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
55
|
+
| `--mw-primary-color` | Brand colour as a **fill**: primary buttons, table headers, bars, badges - the label on top is `--mw-primary-accent-text-color` |
|
|
56
|
+
| `--mw-primary-text-color` | Brand colour as **ink** on a theme surface: text, icons, focus rings, accent borders. Derived by clamping OKLch lightness (`max(l, .68)` on dark, `min(l, .55)` on light), so a colour already in range is used untouched |
|
|
57
|
+
| `--mw-primary-color-hover` | Solid hover surface (derived: base + `$hover-shift` black, in both themes) |
|
|
58
|
+
| `--mw-primary-background` | 20% tint - focus halo, alert/badge/tag surface, scrollbar tracks |
|
|
59
|
+
| `--mw-primary-background-hover` | 45% tint - row and list hover |
|
|
60
|
+
| `--mw-primary-info-background` | Alias of `--mw-primary-background`, so a component can interpolate one name across all six colours |
|
|
61
|
+
| `--mw-border-accent` | Translucent accent **line**: panel rules, dividers, tab underlines. Theme-aware (70% of `--mw-*-text-color`) |
|
|
62
|
+
| `--mw-secondary-*` | Same set for the second brand colour |
|
|
63
|
+
| `--mw-success/warning/danger/info-color` | Status colours, each with `-text-color`, `-color-hover`, `-info-background`, `-info-background-hover` |
|
|
64
|
+
| `--mw-accent-text-color` | Text on any solid coloured surface (buttons, table/panel headers, badges, stepper dots) |
|
|
65
|
+
| `--mw-primary-accent-text-color` | Per colour override of that label. Same for `secondary`, `success`, `warning`, `danger`, `info`. Defaults to `--mw-accent-text-color`, so set one only when a colour needs the opposite label - a neon primary on a dark palette |
|
|
66
|
+
| `--mw-gray-color` | Neutral foreground: muted icons, tooltips |
|
|
67
|
+
| `--mw-gray-background` | Subtle neutral surface (20% alpha): zebra rows, disabled fields, tracks, skeletons |
|
|
68
|
+
| `--mw-corner-accent` | The accent arc on the two round corners of every card, panel, modal and tile, and on the top-right corner of an avatar. Theme-aware: the full `--mw-*-text-color` tone in the dark theme, held to 80% in the light one, where the same blue carries far more contrast on a near-white card. Restyle it to recolour the signature, or `mw-corner-plain` on a single box to drop it |
|
|
69
|
+
| `--mw-surface-muted` | Alias of `--mw-gray-background` under the name you reach for: a slightly set-off area _inside_ a card - hint block, framed paragraph, form summary |
|
|
70
|
+
| `--mw-overlay-background` | Heavy scrim (60%) behind modals and blocking spinners |
|
|
71
|
+
| `--mw-page-background`, `--mw-card-background`, `--mw-footer-background`, `--mw-border`, `--mw-shadow`, `--mw-text-color`, `--mw-text-muted-color`, `--mw-hero-image-filter` | The **active theme** - aliases pointing at the `--mw-dark-*` or `--mw-light-*` set |
|
|
72
|
+
| `--mw-header-*` | Header chrome: `background`, `text-color`, `navbar-list-color`, `navbar-list-active-color`, `burgerbutton-color`, `burgerbutton-open-color`, `border` - dark in both themes. The two burger tokens default to the primary and secondary label ink, because the burger sits on those two surfaces |
|
|
73
|
+
| `--mw-form-elements-background`, `--mw-form-elements-color` | Form controls stay light in both themes and therefore have their own pair |
|
|
74
|
+
| `--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 |
|
|
75
|
+
| `--mw-hero-background`, `--mw-hero-text-color` | Hero image (`url(...)`) and the ink on it. Fixed across themes - the photo does not change with the theme, so its text must not either. Defaults to the light end of the palette |
|
|
76
|
+
| `--mw-transition` | Hover and focus states - an explicit paint-only property list at `--mw-duration-base`, never `all` |
|
|
77
|
+
| `--mw-card-img-height` | Per-card image height (default `210px`; `mw-card-lg`/`-xl` set it to 340px/480px, 260px/340px below `sm`) |
|
|
78
|
+
| `--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 |
|
|
79
|
+
| `--mw-card-addon-text-color` | Label on that badge/ribbon; the `mw-card-addon-*` classes point it at the matching `--mw-*-accent-text-color` |
|
|
80
|
+
| `--mw-progress-ink` | Label inside `mw-progress-inline-label`; the `mw-progress-*` colour classes point it at the matching `--mw-*-accent-text-color` |
|
|
81
|
+
| `--mw-table-scroll-height` | Per-table height cap for `mw-table-responsive-scroll` |
|
|
82
|
+
| `--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`) |
|
|
83
|
+
| `--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)`) |
|
|
84
|
+
| `--mw-section-padding-block` | Top/bottom rhythm of `mw-section` (3.3rem, stepping down to 2.5rem below `md` and 1.75rem below `sm`) |
|
|
85
|
+
| `--mw-section-padding-fluid` | The fluid alternative to the value above - 1.75rem on a phone up to 5.5rem at `xl`. Not applied by itself: set `--mw-section-padding-block: var(--mw-section-padding-fluid)` |
|
|
86
|
+
| `--mw-section-padding-compact`, `--mw-section-padding-airy` | The two presets, as tokens so the phone steps reach them - point `--mw-section-padding-block` at one |
|
|
87
|
+
| `--mw-section-head-step` | One step of the head rhythm, derived from `--mw-section-padding-block`. Every measure in a head and around a subtitle is a multiple of it, so a spacing preset moves them all |
|
|
88
|
+
| `--mw-section-nav-height` | Height the sticky `mw-section-nav` reserves (3.75rem). A page carrying a strip adds it to `scroll-padding-top` itself, through the offset token below |
|
|
89
|
+
| `--mw-announcement-offset`, `--mw-section-nav-offset` | What each layer of sticky chrome below the header adds to `scroll-padding-top`. `0px` until the component switches it on, so a page with both a ribbon and a strip reserves for both. For a sticky bar of your own, override `scroll-padding-top` on `html` - the calc names these two |
|
|
90
|
+
| `--mw-root-font-size` | Percentage the whole rem scale is built on (`100%`). Type, spacing and control heights move with it; px breakpoints do not |
|
|
91
|
+
| `--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 |
|
|
92
|
+
| `--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` |
|
|
93
|
+
| `--mw-elevation-1` … `-5` | Every shadow in the framework. Two layers per level - contact plus ambient. Never write a `box-shadow` by hand: a hand-rolled one is the wrong colour in one of the two themes |
|
|
94
|
+
| `--mw-shadow-near`, `--mw-shadow-far` | The two tones the ramp above is mixed from, per theme |
|
|
95
|
+
| `--mw-transition-fast` | The same property list at `--mw-duration-fast` - for a state change that should feel instant under the pointer |
|
|
96
|
+
| `--mw-duration-instant\|fast\|base\|slow\|slower` | 110 / 180 / 300 / 520 / 900ms. Anything built on these is covered by `prefers-reduced-motion` for free |
|
|
97
|
+
| `--mw-duration-zoom` | 650ms, for a large surface actually travelling - an image scaling inside a card, a slider track |
|
|
98
|
+
| `--mw-ease-out`, `--mw-ease-in-out`, `--mw-ease-spring` | Things arriving (the default) / A to B and back / a pop |
|
|
99
|
+
| `--mw-control-height-sm\|·\|lg`, `--mw-control-font-sm\|·\|lg`, `--mw-control-line-height` | One size scale for input, select, textarea and button, so a field and the button beside it line up by construction |
|
|
100
|
+
| `--mw-focus-ring-width\|offset\|color` | The keyboard focus ring |
|
|
101
|
+
| `--mw-focus-halo-size\|opacity` | The soft ring a form field gets instead of a hard outline |
|
|
102
|
+
| `--mw-internal-theme-mode` | Read-only: what `$mw-theme-mode` was compiled to |
|
|
103
103
|
|
|
104
104
|
`--mw-container-gutter`, `--mw-container-width` and `--mw-section-padding-block`
|
|
105
105
|
are the knobs a good default cannot settle, because the right answer differs per
|
|
@@ -523,4 +523,6 @@ Details worth knowing:
|
|
|
523
523
|
(`utilities`, `form-elements`), wasteful for `components`.
|
|
524
524
|
- Some components expect a sibling: `lists` styles checkbox rows and looks best
|
|
525
525
|
with `form-elements/checkbox`; `tags` uses `mw-btn-mini` from `buttons` for
|
|
526
|
-
its remove button.
|
|
526
|
+
its remove button. `mosaic` needs `lightbox` for its viewer, and
|
|
527
|
+
`portrait-gallery` needs `utilities/fit` for a photo it shows whole instead of
|
|
528
|
+
cropping. `overlay-btn` comes along with every component that uses it.
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,16 @@ 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.29.0] - 2026-09-23
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- new gallery styles
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- removed some duplicated html showcase with toggle buttons for variants
|
|
18
|
+
|
|
9
19
|
## [5.28.0] - 2026-09-21
|
|
10
20
|
|
|
11
21
|
### Changed
|
package/CLAUDE.md
CHANGED
|
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
4
4
|
|
|
5
5
|
## Project Overview
|
|
6
6
|
|
|
7
|
-
MaverickWave is a lightweight, modern CSS framework providing a grid system,
|
|
7
|
+
MaverickWave is a lightweight, modern CSS framework providing a grid system, 59 UI components, utility classes, and light/dark mode support. The repo also contains the showcase/documentation website bundled into the distribution.
|
|
8
8
|
|
|
9
9
|
## Commands
|
|
10
10
|
|
|
@@ -30,7 +30,7 @@ There are no test or lint scripts.
|
|
|
30
30
|
|
|
31
31
|
- `abstracts/` - CSS custom properties, mixins, SCSS functions (color variant generation)
|
|
32
32
|
- `base/` - Reset, element defaults, typography
|
|
33
|
-
- `components/` - Self-contained component styles (
|
|
33
|
+
- `components/` - Self-contained component styles (59 files, one per component)
|
|
34
34
|
- `form-elements/` - Form input/select/checkbox-specific styles
|
|
35
35
|
- `layout/` - Grid, container, header/footer, section
|
|
36
36
|
- `utilities/` - Spacing, flex, display utility classes
|
|
@@ -40,9 +40,9 @@ There are no test or lint scripts.
|
|
|
40
40
|
to it. `media-down($bp)` only for rules that set what the base never sets, or
|
|
41
41
|
where the narrow layout costs more properties than the wide one.
|
|
42
42
|
|
|
43
|
-
**JavaScript** (`src/js/main.js`) - Single file. All components auto-initialize on `DOMContentLoaded`. Includes: gallery and image sliders, theme toggle (persisted to localStorage, transitions suppressed during the flip), accordion, mobile nav, progress bar (IntersectionObserver), scroll spy, tabs (which also get their ARIA and arrow-key handling here), alerts/toasts, modals, range inputs, dropdowns, language switcher, checkbox lists, kanban board, calendar.
|
|
43
|
+
**JavaScript** (`src/js/main.js`) - Single file. All components auto-initialize on `DOMContentLoaded`. Includes: gallery and image sliders, theme toggle (persisted to localStorage, transitions suppressed during the flip), accordion, mobile nav, progress bar (IntersectionObserver), scroll spy, tabs (which also get their ARIA and arrow-key handling here), alerts/toasts, modals, range inputs, dropdowns, language switcher, checkbox lists, kanban board, calendar, portrait gallery, mosaic, lightbox, story reels.
|
|
44
44
|
|
|
45
|
-
**HTML showcase** (`index.html` + `src/partials/`) - The top-level `index.html` uses `@@include()` syntax to pull in
|
|
45
|
+
**HTML showcase** (`index.html` + `src/partials/`) - The top-level `index.html` uses `@@include()` syntax to pull in 72 partials from `src/partials/`. These compile into `dist/index.html`.
|
|
46
46
|
|
|
47
47
|
## Naming Conventions
|
|
48
48
|
|
package/README.md
CHANGED
|
@@ -45,12 +45,12 @@ The result is a framework that balances utility with simplicity, offering develo
|
|
|
45
45
|
<title>My MaverickWave Project</title>
|
|
46
46
|
<link
|
|
47
47
|
rel="stylesheet"
|
|
48
|
-
href="https://cdn.jsdelivr.net/npm/maverick-wave@5.
|
|
48
|
+
href="https://cdn.jsdelivr.net/npm/maverick-wave@5.29.0/maverick-wave.min.css"
|
|
49
49
|
/>
|
|
50
50
|
</head>
|
|
51
51
|
<body>
|
|
52
52
|
<!-- Your content here -->
|
|
53
|
-
<script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.
|
|
53
|
+
<script src="https://cdn.jsdelivr.net/npm/maverick-wave@5.29.0/maverick-wave.min.js"></script>
|
|
54
54
|
</body>
|
|
55
55
|
</html>
|
|
56
56
|
```
|