maverick-wave 4.3.0 → 4.4.1
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/maverick-wave/SKILL.md +5 -3
- package/.claude/skills/maverick-wave/examples/angular-form.md +4 -0
- package/.claude/skills/maverick-wave/examples/static-landing-page.md +1 -1
- package/.claude/skills/maverick-wave/references/forms.md +27 -0
- package/.claude/skills/maverick-wave/references/theming.md +91 -67
- package/CHANGELOG.md +16 -0
- package/CLAUDE.md +10 -10
- package/README.md +109 -31
- package/maverick-wave.min.css +2 -2
- package/package.json +2 -2
- package/scripts/verify.js +13 -7
- package/src/assets/header-logo.svg +4 -4
- package/src/js/main.js +3 -3
- package/src/partials/accordions-container.html +9 -9
- package/src/partials/blog-posts-container.html +1 -1
- package/src/partials/buttons-container.html +1 -1
- package/src/partials/colors-container.html +75 -3
- package/src/partials/footer-container.html +3 -3
- package/src/partials/form-elements-container.html +98 -0
- package/src/partials/form-field-container.html +20 -4
- package/src/partials/get-started-container.html +36 -33
- package/src/partials/header-utilities-container.html +1 -1
- package/src/partials/modals-container.html +1 -1
- package/src/partials/ratings-container.html +1 -1
- package/src/partials/segmented-container.html +2 -2
- package/src/partials/tables-container.html +4 -4
- package/src/partials/tabs-container.html +7 -6
- package/src/partials/tags-container.html +1 -1
- package/src/partials/timelines-container.html +5 -5
- package/src/partials/utilities-container.html +1 -1
- package/src/scss/abstracts/_variables.scss +158 -46
- package/src/scss/base/_base.scss +1 -1
- package/src/scss/base/_typography.scss +2 -2
- package/src/scss/components/_alerts.scss +2 -2
- package/src/scss/components/_avatars.scss +2 -2
- package/src/scss/components/_blog-post.scss +5 -5
- package/src/scss/components/_breadcrumbs.scss +3 -3
- package/src/scss/components/_button-bar.scss +4 -4
- package/src/scss/components/_buttons.scss +6 -6
- package/src/scss/components/_calendar.scss +10 -10
- package/src/scss/components/_cards.scss +2 -2
- package/src/scss/components/_divider.scss +3 -3
- package/src/scss/components/_empty-state.scss +4 -4
- package/src/scss/components/_gallery.scss +1 -1
- package/src/scss/components/_info.scss +3 -3
- package/src/scss/components/_kanban.scss +12 -12
- package/src/scss/components/_lists.scss +12 -12
- package/src/scss/components/_localhost-indicator.scss +2 -2
- package/src/scss/components/_meta-info.scss +1 -1
- package/src/scss/components/_ratings.scss +1 -1
- package/src/scss/components/_segmented.scss +3 -3
- package/src/scss/components/_spinners.scss +10 -10
- package/src/scss/components/_stepper.scss +4 -4
- package/src/scss/components/_tabs.scss +5 -5
- package/src/scss/components/_techstack-bucket.scss +2 -2
- package/src/scss/components/_timelines.scss +10 -10
- package/src/scss/form-elements/_checkbox.scss +1 -1
- package/src/scss/form-elements/_form.scss +4 -4
- package/src/scss/form-elements/_index.scss +1 -0
- package/src/scss/form-elements/_input-group.scss +1 -1
- package/src/scss/form-elements/_input.scss +3 -3
- package/src/scss/form-elements/_login.scss +2 -2
- package/src/scss/form-elements/_prefilled.scss +65 -0
- package/src/scss/form-elements/_select.scss +2 -2
- package/src/scss/form-elements/_slider.scss +1 -1
- package/src/scss/form-elements/_textarea.scss +2 -2
- package/src/scss/layout/_footer.scss +3 -3
- package/src/scss/layout/_header.scss +5 -5
- package/src/scss/layout/_section.scss +5 -5
- package/src/scss/utilities/_flex.scss +1 -1
- package/src/scss/utilities/_text.scss +6 -6
|
@@ -186,7 +186,8 @@ Everything below is documented in `references/components.md` unless marked other
|
|
|
186
186
|
|
|
187
187
|
**Forms** (`references/forms.md`) `mw-field` · `mw-input` · `mw-select` ·
|
|
188
188
|
`mw-textarea` · `mw-checkbox` · `mw-radio` · `mw-toggle` · `mw-slider` ·
|
|
189
|
-
`mw-input-group` · `mw-
|
|
189
|
+
`mw-input-group` · `mw-prefilled` · `mw-form` / `mw-form-group` /
|
|
190
|
+
`mw-form-actions` · `mw-login`
|
|
190
191
|
|
|
191
192
|
**Layout** (`references/layout.md`) `mw-main` · `mw-container` · `mw-content` ·
|
|
192
193
|
`mw-section` · `mw-page-header` · `mw-grid-*` · `mw-row-split` · `mw-hero` ·
|
|
@@ -229,8 +230,9 @@ text
|
|
|
229
230
|
backgrounds and borders are derived with `color-mix()` at runtime. Setting
|
|
230
231
|
`--mw-primary-color-hover` by hand is usually a sign the base token was not
|
|
231
232
|
set.
|
|
232
|
-
10. **Browser floor: `color-mix()`** - Chrome
|
|
233
|
-
|
|
233
|
+
10. **Browser floor: `color-mix()` and `oklch(from ...)`** - Chrome 119+,
|
|
234
|
+
Safari 16.4+, Firefox 128+. Both carry the derived tones, so older browsers
|
|
235
|
+
get no colours at all, not merely worse ones.
|
|
234
236
|
11. **Touch targets grow on their own.** On `pointer: coarse` or below 768px,
|
|
235
237
|
`mw-btn-sm`, `mw-input-sm`, `mw-select-sm` and `mw-textarea-sm` get a 2.5rem
|
|
236
238
|
minimum height, a tab 2.75rem, a calendar day 44px. `mw-btn-mini` keeps its
|
|
@@ -238,6 +238,10 @@ export class ProjectFormComponent {
|
|
|
238
238
|
container - use `mw-form-element-error` instead.
|
|
239
239
|
- **`disabled`/`readonly` are attributes**, not classes. With reactive forms use
|
|
240
240
|
`control.disable()`; the muted look comes from the `:disabled` selector.
|
|
241
|
+
- **Prefilled values** take `mw-prefilled` on the control, not on the wrapper.
|
|
242
|
+
In an edit form that starts from `patchValue()`, bind it to your own flag:
|
|
243
|
+
`[class.mw-prefilled]="loaded() && !form.controls.name.dirty"`. Repeat the
|
|
244
|
+
information in the `mw-field-hint`, the marker itself is decoration.
|
|
241
245
|
- **The slider needs two bindings**: `data-value` for the badge text,
|
|
242
246
|
`--value` for the filled part of the track.
|
|
243
247
|
- **A spinner inside a button** needs its shape class (`mw-spinner-border`) plus
|
|
@@ -26,7 +26,7 @@ wired up by hand.
|
|
|
26
26
|
/* Brand colours - one token per family, the rest is derived */
|
|
27
27
|
:root {
|
|
28
28
|
--mw-primary-color: #0f766e;
|
|
29
|
-
--mw-secondary-color: #
|
|
29
|
+
--mw-secondary-color: #b45309;
|
|
30
30
|
--mw-hero-background: url('/assets/hero.jpg');
|
|
31
31
|
}
|
|
32
32
|
</style>
|
|
@@ -170,6 +170,33 @@ Sizes: `mw-textarea-sm`, `mw-textarea-lg`. Resizing is off by default; enable it
|
|
|
170
170
|
with `mw-textarea-resizable`, `mw-textarea-resizable-vertical` or
|
|
171
171
|
`mw-textarea-resizable-horizontal`.
|
|
172
172
|
|
|
173
|
+
## Prefilled values
|
|
174
|
+
|
|
175
|
+
`mw-prefilled` marks a control whose value did not come from the user in this
|
|
176
|
+
session - loaded from an existing record, restored from a draft, filled with a
|
|
177
|
+
default. It draws a small triangle into the top left corner of the control.
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<input type="text" class="mw-input mw-prefilled" value="Max Mustermann" />
|
|
181
|
+
<select class="mw-select mw-select-sm mw-prefilled">
|
|
182
|
+
...
|
|
183
|
+
</select>
|
|
184
|
+
<textarea class="mw-textarea mw-prefilled" rows="3"></textarea>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
- Works on `mw-input`, `mw-select` and `mw-textarea`, and goes on the control
|
|
188
|
+
itself, not on the `mw-field` wrapper - so it also works in an input group or
|
|
189
|
+
on a standalone control.
|
|
190
|
+
- The triangle follows the size modifier (`mw-input-sm`, `mw-select-lg`, ...)
|
|
191
|
+
and stays visible on `readonly` and `disabled` controls.
|
|
192
|
+
- Colour is `--mw-info-color`, deliberately not primary or danger: it is an
|
|
193
|
+
information about the value, not a state or an error.
|
|
194
|
+
- Decoration only. Screen readers do not see it, so put the same information in
|
|
195
|
+
an `mw-field-hint` and reference it with `aria-describedby`.
|
|
196
|
+
- It is drawn as a background layer, not a pseudo element (`input` and `select`
|
|
197
|
+
never render `::before`/`::after`). A rule that sets the `background`
|
|
198
|
+
shorthand on the same control wipes it - use `background-color` there.
|
|
199
|
+
|
|
173
200
|
## Checkbox
|
|
174
201
|
|
|
175
202
|
The native input is hidden; `mw-checkbox-box` is the visible control, so the
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## The model
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
runtime** with `color-mix()
|
|
7
|
-
whole family - hover tone, translucent backgrounds,
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Thirteen colours are configured, everything else is derived from them **at
|
|
6
|
+
runtime** with `color-mix()` and relative colour syntax. Overriding a root token
|
|
7
|
+
therefore retunes its whole family - hover tone, translucent backgrounds,
|
|
8
|
+
borders, the theme's surface stack, the ink variant the dark theme needs. That is
|
|
9
|
+
the difference to pre-3.4.0, where derived values were baked in at compile time
|
|
10
|
+
and a palette switch meant setting 41 variables.
|
|
11
|
+
|
|
12
|
+
Browser floor for that: `color-mix()` **and** `oklch(from ...)` - Chrome 119+,
|
|
13
|
+
Safari 16.4+, Firefox 128+.
|
|
10
14
|
|
|
11
15
|
```css
|
|
12
16
|
/* loaded after maverick-wave.min.css */
|
|
@@ -14,21 +18,22 @@ a palette switch meant setting 41 variables.
|
|
|
14
18
|
--mw-primary-color: #0f766e; /* also retunes hover, backgrounds, border accent */
|
|
15
19
|
--mw-secondary-color: #f39c12;
|
|
16
20
|
|
|
17
|
-
--mw-success-color: #
|
|
18
|
-
--mw-warning-color: #
|
|
19
|
-
--mw-danger-color: #
|
|
20
|
-
--mw-info-color: #
|
|
21
|
+
--mw-success-color: #157f4b;
|
|
22
|
+
--mw-warning-color: #bda817;
|
|
23
|
+
--mw-danger-color: #c42b1c;
|
|
24
|
+
--mw-info-color: #14618f;
|
|
21
25
|
|
|
22
|
-
--mw-gray-color: #
|
|
26
|
+
--mw-gray-color: #5a6478;
|
|
23
27
|
|
|
24
|
-
--mw-dark-page-background: #
|
|
25
|
-
--mw-dark-text-color: #
|
|
26
|
-
--mw-light-page-background: #
|
|
27
|
-
--mw-light-text-color: #
|
|
28
|
+
--mw-dark-page-background: #171f30;
|
|
29
|
+
--mw-dark-text-color: #e8ecf1;
|
|
30
|
+
--mw-light-page-background: #f2f5f8;
|
|
31
|
+
--mw-light-text-color: #0c1119;
|
|
28
32
|
|
|
29
|
-
--mw-form-elements-background: #
|
|
33
|
+
--mw-form-elements-background: #f4f7fb;
|
|
30
34
|
|
|
31
|
-
/* text on every solid coloured surface
|
|
35
|
+
/* text on every solid coloured surface, and the one token that cannot be
|
|
36
|
+
derived: light brand colours need a dark label, dark ones a light label */
|
|
32
37
|
--mw-accent-text-color: #ffffff;
|
|
33
38
|
|
|
34
39
|
--mw-font-family-base: 'Inter', sans-serif;
|
|
@@ -37,48 +42,55 @@ a palette switch meant setting 41 variables.
|
|
|
37
42
|
|
|
38
43
|
## Which token for what
|
|
39
44
|
|
|
40
|
-
| Token | Role
|
|
41
|
-
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
42
|
-
| `--mw-primary-color` | Brand colour
|
|
43
|
-
| `--mw-primary-color
|
|
44
|
-
| `--mw-primary-
|
|
45
|
-
| `--mw-primary-background
|
|
46
|
-
| `--mw-primary-
|
|
47
|
-
| `--mw-
|
|
48
|
-
| `--mw-
|
|
49
|
-
| `--mw-
|
|
50
|
-
| `--mw-
|
|
51
|
-
| `--mw-
|
|
52
|
-
| `--mw-gray-
|
|
53
|
-
| `--mw-
|
|
54
|
-
| `--mw-
|
|
55
|
-
| `--mw-
|
|
56
|
-
| `--mw-
|
|
57
|
-
| `--mw-
|
|
58
|
-
| `--mw-
|
|
59
|
-
| `--mw-
|
|
60
|
-
| `--mw-
|
|
61
|
-
| `--mw-
|
|
62
|
-
| `--mw-card-
|
|
63
|
-
| `--mw-
|
|
64
|
-
| `--mw-
|
|
65
|
-
| `--mw-
|
|
66
|
-
| `--mw-
|
|
67
|
-
| `--mw-
|
|
68
|
-
| `--mw-
|
|
69
|
-
| `--mw-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
45
|
+
| Token | Role |
|
|
46
|
+
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `--mw-primary-color` | Brand colour as a **fill**: primary buttons, table headers, bars, badges - the label on top is `--mw-accent-text-color` |
|
|
48
|
+
| `--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 |
|
|
49
|
+
| `--mw-primary-color-hover` | Solid hover surface (derived: base + `$hover-shift` black, in both themes) |
|
|
50
|
+
| `--mw-primary-background` | 20% tint - focus halo, alert/badge/tag surface, scrollbar tracks |
|
|
51
|
+
| `--mw-primary-background-hover` | 45% tint - row and list hover |
|
|
52
|
+
| `--mw-primary-info-background` | Alias of `--mw-primary-background`, so a component can interpolate one name across all six colours |
|
|
53
|
+
| `--mw-border-accent` | Translucent accent **line**: panel rules, dividers, tab underlines. Theme-aware (70% of `--mw-*-text-color`) |
|
|
54
|
+
| `--mw-secondary-*` | Same set for the second brand colour |
|
|
55
|
+
| `--mw-success/warning/danger/info-color` | Status colours, each with `-text-color`, `-color-hover`, `-info-background`, `-info-background-hover` |
|
|
56
|
+
| `--mw-accent-text-color` | Text on any solid coloured surface (buttons, table/panel headers, badges, stepper dots) |
|
|
57
|
+
| `--mw-gray-color` | Neutral foreground: muted icons, tooltips |
|
|
58
|
+
| `--mw-gray-background` | Subtle neutral surface (20% alpha): zebra rows, disabled fields, tracks, skeletons |
|
|
59
|
+
| `--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 |
|
|
60
|
+
| `--mw-overlay-background` | Heavy scrim (60%) behind modals and blocking spinners |
|
|
61
|
+
| `--mw-page-background`, `--mw-card-background`, `--mw-footer-background`, `--mw-border`, `--mw-shadow`, `--mw-text-color`, `--mw-text-muted-color`, `--mw-hero-overlay-background` | The **active theme** - aliases pointing at the `--mw-dark-*` or `--mw-light-*` set |
|
|
62
|
+
| `--mw-header-*` | Header chrome: `background`, `text-color`, `navbar-list-color`, `navbar-list-active-color`, `burgerbutton-color`, `border` - dark in both themes |
|
|
63
|
+
| `--mw-form-elements-background`, `--mw-form-elements-color` | Form controls stay light in both themes and therefore have their own pair |
|
|
64
|
+
| `--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 |
|
|
65
|
+
| `--mw-hero-background` | Hero image (`url(...)`) |
|
|
66
|
+
| `--mw-transition` | Global transition (`all 0.3s ease`) |
|
|
67
|
+
| `--mw-card-img-height` | Per-card image height (default `210px`; `mw-card-lg`/`-xl` set it to 340px/480px) |
|
|
68
|
+
| `--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 |
|
|
69
|
+
| `--mw-table-scroll-height` | Per-table height cap for `mw-table-responsive-scroll` |
|
|
70
|
+
| `--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`) |
|
|
71
|
+
| `--mw-container-width`, `--mw-container-width-sm` | Content width of `mw-container` (`min(1200px, 89%)`, below 576px a 1rem gutter) |
|
|
72
|
+
| `--mw-section-padding-block` | Top/bottom rhythm of `mw-section` (1.75rem) |
|
|
73
|
+
| `--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 |
|
|
74
|
+
| `--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` |
|
|
75
|
+
| `--mw-internal-theme-mode` | Read-only: what `$mw-theme-mode` was compiled to |
|
|
76
|
+
|
|
77
|
+
`--mw-container-width`, `--mw-container-width-sm` and
|
|
78
|
+
`--mw-section-padding-block` are the knobs a good default cannot settle, because
|
|
79
|
+
the right answer differs per project: what reads as generous on a landing page
|
|
80
|
+
costs visible content in an application with a sticky header.
|
|
74
81
|
|
|
75
82
|
Two rules that prevent most colour bugs:
|
|
76
83
|
|
|
77
|
-
1. **
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
1. **Fill or ink.** A colour that _fills_ something is `--mw-*-color`; a colour
|
|
85
|
+
_drawn on_ a theme surface - text, icon, focus ring, accent border, thin
|
|
86
|
+
divider - is `--mw-*-text-color`. A colour picked to carry a label is by
|
|
87
|
+
definition unreadable on the page it sits on, so ink is always the
|
|
88
|
+
`-text-color` variant. For a generic rule or outline use `--mw-border-accent`
|
|
89
|
+
or `--mw-border`.
|
|
80
90
|
2. **`--mw-text-muted-color` is only for text on theme surfaces** (cards, page
|
|
81
|
-
background) - it follows the theme.
|
|
91
|
+
background) - it follows the theme. It is a true gray with `$muted-tint`
|
|
92
|
+
(12%) of the primary mixed in, not a stepped-back text colour, so it stays
|
|
93
|
+
gray no matter how tinted the palette is. On a colour surface that stays the same
|
|
82
94
|
in both themes it is always wrong: use `--mw-accent-text-color`, or `opacity`
|
|
83
95
|
for a disabled look.
|
|
84
96
|
|
|
@@ -86,6 +98,11 @@ Two rules that prevent most colour bugs:
|
|
|
86
98
|
|
|
87
99
|
- Dark is the base. Light is applied by putting `mw-theme-light` on `<body>` -
|
|
88
100
|
that class only re-points the theme aliases at the `--mw-light-*` set.
|
|
101
|
+
- Card, footer and border are derived from the page background by scaling its
|
|
102
|
+
OKLch lightness and chroma by one factor. A card steps **away from the text
|
|
103
|
+
colour** - darker than the page in the dark theme, lighter in the light one.
|
|
104
|
+
A near-black `--mw-dark-page-background` leaves no headroom underneath and
|
|
105
|
+
cards collapse into it; keep it around OKLch lightness 0.24.
|
|
89
106
|
- Header, footer chrome and form controls deliberately stay dark/light
|
|
90
107
|
respectively in both themes.
|
|
91
108
|
- Persisting the choice, the toggle UI and the initial class are the
|
|
@@ -106,17 +123,23 @@ effect, because the root colours are declared with `!default`.
|
|
|
106
123
|
$mw-theme-mode: 'switchable',
|
|
107
124
|
// 'switchable' | 'dark' | 'light'
|
|
108
125
|
$primary-color: #0f766e,
|
|
109
|
-
$secondary-color: #
|
|
110
|
-
$success-color: #
|
|
111
|
-
$warning-color: #
|
|
112
|
-
$danger-color: #
|
|
113
|
-
$info-color: #
|
|
114
|
-
$gray-color: #
|
|
115
|
-
$dark-background: #
|
|
116
|
-
$dark-text-color: #
|
|
117
|
-
$light-background: #
|
|
118
|
-
$light-text-color: #
|
|
119
|
-
$form-elements-background: #
|
|
126
|
+
$secondary-color: #b45309,
|
|
127
|
+
$success-color: #15803d,
|
|
128
|
+
$warning-color: #a16207,
|
|
129
|
+
$danger-color: #b91c1c,
|
|
130
|
+
$info-color: #0e7490,
|
|
131
|
+
$gray-color: #64748b,
|
|
132
|
+
$dark-background: #172127,
|
|
133
|
+
$dark-text-color: #e8eef0,
|
|
134
|
+
$light-background: #f2f6f7,
|
|
135
|
+
$light-text-color: #172127,
|
|
136
|
+
$form-elements-background: #f5f9fa,
|
|
137
|
+
$accent-text-color: #f2fafa,
|
|
138
|
+
// the three derivation knobs, all optional
|
|
139
|
+
$hover-shift: 15%,
|
|
140
|
+
$ink-lightness-dark: 0.68,
|
|
141
|
+
$ink-lightness-light: 0.55,
|
|
142
|
+
$muted-tint: 12%,
|
|
120
143
|
$mw-hero-image: url('/assets/hero.jpg'),
|
|
121
144
|
$font-family-base: (
|
|
122
145
|
'Inter',
|
|
@@ -162,7 +185,7 @@ they are all `var()` references anyway:
|
|
|
162
185
|
|
|
163
186
|
## Importing only what you need
|
|
164
187
|
|
|
165
|
-
The full stylesheet is ~
|
|
188
|
+
The full stylesheet is ~172 kB raw / ~26 kB gzipped. Marketing components
|
|
166
189
|
(`blog-post`, `gallery`, `content-slider`, `techstack-bucket`, `tiles`,
|
|
167
190
|
`coming-soon`, `ratings`, `home`, `hero`) are dead weight in an application, and
|
|
168
191
|
Angular bundle budgets notice.
|
|
@@ -201,7 +224,8 @@ colourless.
|
|
|
201
224
|
@use 'maverick-wave/src/scss/utilities';
|
|
202
225
|
```
|
|
203
226
|
|
|
204
|
-
That set compiles to ~
|
|
227
|
+
That set compiles to ~77 kB raw / ~13 kB gzipped - well under half the full
|
|
228
|
+
build.
|
|
205
229
|
|
|
206
230
|
Details worth knowing:
|
|
207
231
|
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,22 @@ 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.5.0] - 2026-08-21
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- new color concept and new default color palette
|
|
14
|
+
|
|
15
|
+
## [4.4.0] - 2026-08-20
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- prefilled marker for form controls (`mw-prefilled`)
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- disabled select lost its arrow
|
|
24
|
+
|
|
9
25
|
## [4.3.0] - 2026-08-19
|
|
10
26
|
|
|
11
27
|
### Fixed
|
package/CLAUDE.md
CHANGED
|
@@ -21,21 +21,21 @@ There are no test or lint scripts.
|
|
|
21
21
|
|
|
22
22
|
## Architecture
|
|
23
23
|
|
|
24
|
-
**Build pipeline**
|
|
24
|
+
**Build pipeline** - `gulpfile.js` orchestrates everything: SCSS compilation (autoprefixed, minified), JS minification via Terser, HTML templating via `gulp-file-include`, asset copying, and build-info injection (`{{VERSION}}`, `{{LAST_BUILD_DATE}}`, `{{LAST_BUILD_YEAR}}` placeholders replaced in HTML at build time).
|
|
25
25
|
|
|
26
26
|
**SCSS layers** (`src/scss/`) follow an ITCSS-inspired structure:
|
|
27
27
|
|
|
28
|
-
- `abstracts/`
|
|
29
|
-
- `base/`
|
|
30
|
-
- `components/`
|
|
31
|
-
- `form-elements/`
|
|
32
|
-
- `layout/`
|
|
33
|
-
- `utilities/`
|
|
34
|
-
- `main.scss`
|
|
28
|
+
- `abstracts/` - CSS custom properties, mixins, SCSS functions (color variant generation)
|
|
29
|
+
- `base/` - Reset, element defaults, typography
|
|
30
|
+
- `components/` - Self-contained component styles (25+ files, one per component)
|
|
31
|
+
- `form-elements/` - Form input/select/checkbox-specific styles
|
|
32
|
+
- `layout/` - Grid, container, header/footer, section
|
|
33
|
+
- `utilities/` - Spacing, flex, display utility classes
|
|
34
|
+
- `main.scss` - Entry point using `@use`/`@forward` (not `@import`)
|
|
35
35
|
|
|
36
|
-
**JavaScript** (`src/js/main.js`)
|
|
36
|
+
**JavaScript** (`src/js/main.js`) - Single file. All components auto-initialize on `DOMContentLoaded`. Includes: gallery slider, theme toggle (persisted to localStorage), accordion, mobile nav, progress bar (IntersectionObserver), scroll spy, tabs, alerts/toasts, modals, range inputs.
|
|
37
37
|
|
|
38
|
-
**HTML showcase** (`index.html` + `src/partials/`)
|
|
38
|
+
**HTML showcase** (`index.html` + `src/partials/`) - The top-level `index.html` uses `@@include()` syntax to pull in 40+ partials from `src/partials/`. These compile into `dist/index.html`.
|
|
39
39
|
|
|
40
40
|
## Naming Conventions
|
|
41
41
|
|
package/README.md
CHANGED
|
@@ -38,12 +38,12 @@ The result is a framework that balances utility with simplicity, offering develo
|
|
|
38
38
|
<title>My MaverickWave Project</title>
|
|
39
39
|
<link
|
|
40
40
|
rel="stylesheet"
|
|
41
|
-
href="https://cdn.jsdelivr.net/npm/maverick-wave@
|
|
41
|
+
href="https://cdn.jsdelivr.net/npm/maverick-wave@4.4.1/maverick-wave.min.css"
|
|
42
42
|
/>
|
|
43
43
|
</head>
|
|
44
44
|
<body>
|
|
45
45
|
<!-- Your content here -->
|
|
46
|
-
<script src="https://cdn.jsdelivr.net/npm/maverick-wave@
|
|
46
|
+
<script src="https://cdn.jsdelivr.net/npm/maverick-wave@4.4.1/maverick-wave.min.js"></script>
|
|
47
47
|
</body>
|
|
48
48
|
</html>
|
|
49
49
|
```
|
|
@@ -63,33 +63,35 @@ Download `maverick-wave.min.css` and `maverick-wave.min.js` from the [latest rel
|
|
|
63
63
|
|
|
64
64
|
### CSS Custom Properties
|
|
65
65
|
|
|
66
|
-
There are thirteen root color tokens. Everything else
|
|
67
|
-
backgrounds, borders, muted text
|
|
66
|
+
There are thirteen root color tokens. Everything else - hover tones, translucent
|
|
67
|
+
backgrounds, borders, muted text - is derived from them at runtime with
|
|
68
68
|
`color-mix()`, so overriding a root token is enough. Load your stylesheet
|
|
69
69
|
**after** `maverick-wave.min.css`:
|
|
70
70
|
|
|
71
71
|
```css
|
|
72
72
|
:root {
|
|
73
73
|
/* brand */
|
|
74
|
-
--mw-primary-color: #
|
|
75
|
-
--mw-secondary-color: #
|
|
74
|
+
--mw-primary-color: #0f766e;
|
|
75
|
+
--mw-secondary-color: #b45309;
|
|
76
76
|
|
|
77
77
|
/* status */
|
|
78
|
-
--mw-success-color: #
|
|
79
|
-
--mw-warning-color: #
|
|
80
|
-
--mw-danger-color: #
|
|
81
|
-
--mw-info-color: #
|
|
78
|
+
--mw-success-color: #15803d;
|
|
79
|
+
--mw-warning-color: #a16207;
|
|
80
|
+
--mw-danger-color: #b91c1c;
|
|
81
|
+
--mw-info-color: #0e7490;
|
|
82
82
|
|
|
83
83
|
/* neutrals and themes */
|
|
84
|
-
--mw-gray-color: #
|
|
85
|
-
--mw-dark-page-background: #
|
|
86
|
-
--mw-dark-text-color: #
|
|
87
|
-
--mw-light-page-background: #
|
|
88
|
-
--mw-light-text-color: #
|
|
89
|
-
--mw-form-elements-background: #
|
|
90
|
-
|
|
91
|
-
/* text on solid colored
|
|
92
|
-
|
|
84
|
+
--mw-gray-color: #64748b;
|
|
85
|
+
--mw-dark-page-background: #172127;
|
|
86
|
+
--mw-dark-text-color: #e8eef0;
|
|
87
|
+
--mw-light-page-background: #f2f6f7;
|
|
88
|
+
--mw-light-text-color: #172127;
|
|
89
|
+
--mw-form-elements-background: #f5f9fa;
|
|
90
|
+
|
|
91
|
+
/* text on every solid colored surface: buttons, table and panel headers.
|
|
92
|
+
The one token that cannot be derived - a light brand color needs a dark
|
|
93
|
+
label, a dark one a light label. Set it opposite your --mw-primary-color. */
|
|
94
|
+
--mw-accent-text-color: #f2fafa;
|
|
93
95
|
|
|
94
96
|
--mw-font-family-base: 'Your Font Name', sans-serif;
|
|
95
97
|
}
|
|
@@ -97,11 +99,82 @@ backgrounds, borders, muted text — is derived from them at runtime with
|
|
|
97
99
|
|
|
98
100
|
Setting `--mw-primary-color` alone also retunes `--mw-primary-color-hover`,
|
|
99
101
|
`--mw-primary-background`, `--mw-primary-background-hover`,
|
|
100
|
-
`--mw-primary-
|
|
102
|
+
`--mw-primary-text-color` and `--mw-border-accent`. The same holds for
|
|
101
103
|
`--mw-dark-page-background`, which drives the dark card, footer and border
|
|
102
104
|
tones. Each derived token can still be overridden individually if you want to
|
|
103
105
|
break out of the scale.
|
|
104
106
|
|
|
107
|
+
> The derivation needs `color-mix()` **and** relative colour syntax
|
|
108
|
+
> (`oklch(from ...)`): Chrome 119+, Safari 16.4+, Firefox 128+. Older browsers
|
|
109
|
+
> get no colours at all, not merely worse ones.
|
|
110
|
+
|
|
111
|
+
### Fill or ink
|
|
112
|
+
|
|
113
|
+
Every brand and status colour comes in two tokens, and picking the right one is
|
|
114
|
+
the whole trick:
|
|
115
|
+
|
|
116
|
+
- `--mw-primary-color` is the exact colour, for anything it **fills** - buttons,
|
|
117
|
+
badges, bars, progress. The label on top is `--mw-accent-text-color`.
|
|
118
|
+
- `--mw-primary-text-color` is the same colour tuned to the active theme, for
|
|
119
|
+
anything drawn **on** a theme surface - text, icons, focus rings, accent
|
|
120
|
+
borders and dividers.
|
|
121
|
+
|
|
122
|
+
The second one exists because a colour picked to carry a label is by definition
|
|
123
|
+
too dark or too light to be read _on_ the page it sits on. The ink token is
|
|
124
|
+
derived by clamping OKLch lightness and keeping hue and chroma:
|
|
125
|
+
|
|
126
|
+
```css
|
|
127
|
+
--mw-dark-primary-text-color: oklch(
|
|
128
|
+
from var(--mw-primary-color) max(l, 0.68) c h
|
|
129
|
+
);
|
|
130
|
+
--mw-light-primary-text-color: oklch(
|
|
131
|
+
from var(--mw-primary-color) min(l, 0.55) c h
|
|
132
|
+
);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
That is a bound, not a target, which is what makes it work for any palette. A
|
|
136
|
+
dark brand colour gets lifted, a very light one gets deepened, and a colour
|
|
137
|
+
already inside the range passes through untouched - a neon green stays neon on
|
|
138
|
+
the dark page and only turns into a real green on the light one. The bounds are
|
|
139
|
+
`$ink-lightness-dark` and `$ink-lightness-light` in SCSS.
|
|
140
|
+
`--mw-secondary-text-color` and `--mw-success/warning/danger/info-text-color`
|
|
141
|
+
are derived the same way.
|
|
142
|
+
|
|
143
|
+
`--mw-text-muted-color` is built the other way round: a true gray at a fixed
|
|
144
|
+
lightness with `$muted-tint` (12%) of the primary colour mixed in, so the gray
|
|
145
|
+
belongs to the palette without carrying its saturation. Stepping the theme's
|
|
146
|
+
text colour back instead would hand its tint straight through - a mint white
|
|
147
|
+
page would end up with mint green secondary text. Set `$muted-tint: 0%` for a
|
|
148
|
+
neutral gray.
|
|
149
|
+
|
|
150
|
+
Tinted surfaces follow one rule as well: `--mw-*-background` is 20% of the
|
|
151
|
+
colour, `--mw-*-background-hover` 45%. Both stay close enough to the surface
|
|
152
|
+
underneath that `--mw-text-color` keeps working on top, which is what makes an
|
|
153
|
+
alert, badge or tag readable in either theme.
|
|
154
|
+
|
|
155
|
+
### The surface stack
|
|
156
|
+
|
|
157
|
+
Card, footer and border are derived from the page background by scaling its
|
|
158
|
+
OKLch lightness _and_ chroma by one factor, keeping the hue:
|
|
159
|
+
|
|
160
|
+
```css
|
|
161
|
+
--mw-dark-card-background: oklch(
|
|
162
|
+
from var(--mw-dark-page-background) calc(l * 0.75) calc(c * 0.75) h
|
|
163
|
+
);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Both themes step a card **away from their text colour** - down into the dark
|
|
167
|
+
theme, up into the light one - so content always sits on the cleaner of the two
|
|
168
|
+
surfaces. Chroma rides along with lightness because that is what a hand-picked
|
|
169
|
+
stack does: a darker surface of the same hue carries less colour, not the same
|
|
170
|
+
colour at a lower lightness.
|
|
171
|
+
|
|
172
|
+
The one thing to know when picking `--mw-dark-page-background`: it needs
|
|
173
|
+
headroom underneath. On a near-black page the surfaces below it have nowhere to
|
|
174
|
+
go and cards collapse into the background, leaving only the border to separate
|
|
175
|
+
them. The default sits at OKLch lightness 0.24 for that reason. The factors sit
|
|
176
|
+
inline in `$dark-theme-colors` / `$light-theme-colors`, one per surface.
|
|
177
|
+
|
|
105
178
|
### SCSS Source
|
|
106
179
|
|
|
107
180
|
For full control, clone the repository and integrate `src/scss/main.scss` into your Sass build (Dart Sass required). MaverickWave uses modern `@use`/`@forward` syntax. Pass your overrides through `with`:
|
|
@@ -114,14 +187,19 @@ For full control, clone the repository and integrate `src/scss/main.scss` into y
|
|
|
114
187
|
$mw-theme-mode: 'switchable',
|
|
115
188
|
|
|
116
189
|
// Override root colors
|
|
117
|
-
$primary-color: #
|
|
118
|
-
$secondary-color: #
|
|
119
|
-
$dark-background: #
|
|
120
|
-
$light-background: #
|
|
190
|
+
$primary-color: #0f766e,
|
|
191
|
+
$secondary-color: #b45309,
|
|
192
|
+
$dark-background: #172127,
|
|
193
|
+
$light-background: #f2f6f7,
|
|
194
|
+
|
|
195
|
+
// Optional: the three derivation knobs
|
|
196
|
+
$ink-lightness-dark: 0.68,
|
|
197
|
+
$ink-lightness-light: 0.55,
|
|
198
|
+
$muted-tint: 12%
|
|
121
199
|
);
|
|
122
200
|
```
|
|
123
201
|
|
|
124
|
-
> Plain variable assignments before `@use` have no effect
|
|
202
|
+
> Plain variable assignments before `@use` have no effect - the framework
|
|
125
203
|
> declares its root colors with `!default`, which only `@use ... with` feeds.
|
|
126
204
|
|
|
127
205
|
### Importing Only What You Need
|
|
@@ -133,7 +211,7 @@ have no use for the marketing components (`blog-post`, `gallery`,
|
|
|
133
211
|
`home`), and Angular bundle budgets notice the difference.
|
|
134
212
|
|
|
135
213
|
```scss
|
|
136
|
-
// styles.scss
|
|
214
|
+
// styles.scss - configuration first, then pick
|
|
137
215
|
@use 'maverick-wave/src/scss/abstracts/variables' with (
|
|
138
216
|
$primary-color: #0f766e
|
|
139
217
|
);
|
|
@@ -154,7 +232,7 @@ have no use for the marketing components (`blog-post`, `gallery`,
|
|
|
154
232
|
A typical application subset like the one above compiles to roughly 98 kB raw /
|
|
155
233
|
15 kB gzipped, against 147 kB / 22.5 kB for the full build.
|
|
156
234
|
|
|
157
|
-
> **`base` is not optional.** It carries the `:root` custom properties
|
|
235
|
+
> **`base` is not optional.** It carries the `:root` custom properties - without
|
|
158
236
|
> it every component renders without colors. If you bring your own reset, use
|
|
159
237
|
> `@use 'maverick-wave/src/scss/base/base'` for the token block alone.
|
|
160
238
|
> The `with (...)` configuration has to be the first statement in the file,
|
|
@@ -174,7 +252,7 @@ above):
|
|
|
174
252
|
> are never initialized, and the theme toggle mutates the DOM behind Angular's
|
|
175
253
|
> change detection. The behaviors it covers (accordion, tabs, modal close, mobile
|
|
176
254
|
> nav, scroll spy, theme toggle, progress bars, sliders, alerts, galleries) are a
|
|
177
|
-
> few lines each in a component
|
|
255
|
+
> few lines each in a component - the framework's state classes are the whole
|
|
178
256
|
> contract. Theme switching, for example, is a single class on `<body>`:
|
|
179
257
|
|
|
180
258
|
```typescript
|
|
@@ -183,7 +261,7 @@ document.body.classList.toggle('mw-theme-light', isLight);
|
|
|
183
261
|
```
|
|
184
262
|
|
|
185
263
|
The `mw-field` wrapper groups label, control, hint and error. Bind the error
|
|
186
|
-
state yourself
|
|
264
|
+
state yourself - the framework does not style Angular's `ng-invalid` /
|
|
187
265
|
`ng-touched` classes:
|
|
188
266
|
|
|
189
267
|
```html
|
|
@@ -202,8 +280,8 @@ state yourself — the framework does not style Angular's `ng-invalid` /
|
|
|
202
280
|
</div>
|
|
203
281
|
```
|
|
204
282
|
|
|
205
|
-
A complete usage guide for AI coding assistants
|
|
206
|
-
integration pattern and example
|
|
283
|
+
A complete usage guide for AI coding assistants - every component, token,
|
|
284
|
+
integration pattern and example - ships with the package as a Claude Code skill
|
|
207
285
|
in `.claude/skills/maverick-wave/`.
|
|
208
286
|
|
|
209
287
|
## Development
|