maverick-wave 5.23.0 → 5.25.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.
Files changed (38) hide show
  1. package/.claude/skills/mw-maverick-wave/SKILL.md +37 -9
  2. package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +22 -14
  3. package/.claude/skills/mw-maverick-wave/references/components.md +4 -0
  4. package/.claude/skills/mw-maverick-wave/references/javascript.md +44 -8
  5. package/.claude/skills/mw-maverick-wave/references/layout.md +48 -6
  6. package/.claude/skills/mw-maverick-wave/references/theming.md +21 -1
  7. package/CHANGELOG.md +20 -0
  8. package/CLAUDE.md +4 -0
  9. package/README.md +4 -2
  10. package/index.html +75 -38
  11. package/maverick-wave.min.css +5 -5
  12. package/maverick-wave.min.js +1 -1
  13. package/package.json +2 -2
  14. package/src/js/main.js +149 -57
  15. package/src/partials/get-started-container.html +5 -10
  16. package/src/partials/highlights-container.html +7 -5
  17. package/src/partials/input-group-container.html +1 -3
  18. package/src/partials/page-header-container.html +2 -2
  19. package/src/partials/section-head-container.html +74 -0
  20. package/src/partials/tags-container.html +0 -6
  21. package/src/scss/base/_base.scss +6 -1
  22. package/src/scss/components/_blog-post.scss +15 -10
  23. package/src/scss/components/_button-bar.scss +10 -6
  24. package/src/scss/components/_code.scss +23 -34
  25. package/src/scss/components/_info.scss +8 -1
  26. package/src/scss/components/_kanban.scss +6 -6
  27. package/src/scss/components/_meta-info.scss +7 -6
  28. package/src/scss/components/_tables.scss +6 -4
  29. package/src/scss/components/_tiles.scss +20 -30
  30. package/src/scss/layout/_grid.scss +28 -0
  31. package/src/scss/layout/_header.scss +16 -9
  32. package/src/scss/layout/_home.scss +21 -2
  33. package/src/scss/layout/_main.scss +10 -7
  34. package/src/scss/layout/_page-header.scss +4 -4
  35. package/src/scss/layout/_section.scss +117 -47
  36. package/src/scss/main-lean.scss +16 -0
  37. package/src/scss/utilities/_index.scss +1 -0
  38. package/src/scss/utilities/_print.scss +107 -0
@@ -1,65 +1,133 @@
1
1
  @use '../abstracts' as *;
2
2
 
3
3
  @layer mw.layout {
4
- // The rule under a section heading. Shared, so the two levels cannot drift
5
- // apart in width and weight - the subtitle carried the wider mark, which reads
6
- // as the louder one under the smaller heading. Colour is where they do part.
7
- @mixin _section-rule(
8
- $width,
9
- $height,
10
- $offset,
11
- $color: var(--mw-primary-text-color)
12
- ) {
13
- &::after {
4
+ // The head of a section: a rule, a title, and the line that says what the
5
+ // section is. All three left-aligned, and that is the whole point of the
6
+ // component. Centred running text moves its own left edge with every line
7
+ // break, so the eye has to find the start of each line instead of jumping
8
+ // to a fixed position - fine for a heading, tiring from the third line of
9
+ // body copy on. Aligned, title, lead and content below share one edge, and
10
+ // that edge is what holds a section together.
11
+ .mw-section-head {
12
+ position: relative;
13
+ margin-bottom: var(--mw-section-head-gap);
14
+ padding-top: var(--mw-section-head-pad);
15
+ // Two pixels and not one: the diagonal pattern of mw-section-alternate
16
+ // swallows a hairline, and the rule is the thing that has to survive on
17
+ // every background the framework paints.
18
+ border-top: 2px solid var(--mw-border);
19
+
20
+ // The rule stays quiet so it reads as a boundary and not as a border, and
21
+ // quiet is still hard to see on a patterned band. Hence the mark:
22
+ // a short, thicker piece of the accent colour sitting on the line at the
23
+ // edge everything else starts from. It carries the weight the full-width
24
+ // rule deliberately does not have.
25
+ &::before {
14
26
  content: '';
15
27
  position: absolute;
16
- bottom: $offset;
17
- left: 50%;
18
- transform: translateX(-50%);
19
- width: $width;
20
- height: $height;
28
+ top: 0;
29
+ left: 0;
30
+ transform: translateY(-50%);
31
+ width: var(--mw-section-head-mark-width);
32
+ height: 4px;
21
33
  border-radius: radius('xs');
22
- background: $color;
34
+ background: var(--mw-section-head-mark-color);
23
35
  }
24
36
  }
25
37
 
26
- .mw-section-title {
27
- font-size: fluid('2xl', '3xl', $to: 'sm');
28
- margin-bottom: var(--mw-section-title-gap);
29
- text-align: center;
30
- position: relative;
31
-
32
- @include _section-rule(56px, 3px, spacing('-3'));
38
+ .mw-section-head-title {
39
+ margin: spacing('0');
40
+ font-size: fluid('2xl', '4xl', $to: 'lg');
41
+ line-height: 1;
42
+ letter-spacing: -0.02em;
43
+ text-wrap: balance;
33
44
  }
34
45
 
35
- // The lead line under a section title. Every landing page writes this
36
- // paragraph, and it always wants the same four things: centred, muted,
37
- // narrower than the container so it reads as a line rather than a block, and
38
- // pulled up toward the title it belongs to - the title's gap is sized for the
39
- // content below, not for its own subtitle.
40
- .mw-section-intro {
41
- max-width: 46rem;
42
- margin: spacing('-3') auto spacing('9');
46
+ // Two limits, and the narrower one wins: 65 characters is where a line stops
47
+ // being comfortable, four fifths is what keeps the paragraph from filling the
48
+ // container edge to edge on a wide screen. Below md only the character count
49
+ // is left - four fifths of a phone is a column nothing fits in.
50
+ .mw-section-head-intro {
51
+ max-width: 75ch;
52
+ margin: spacing('4') spacing('0') spacing('0');
43
53
  font-size: font-size('md');
54
+ line-height: 1.6;
44
55
  color: var(--mw-text-muted-color);
45
- text-align: center;
46
- text-wrap: balance;
56
+ text-wrap: pretty;
57
+
58
+ @include media-up('md') {
59
+ max-width: min(80%, 70ch);
60
+ }
61
+
62
+ p {
63
+ margin: spacing('0');
64
+ }
65
+
66
+ p + p {
67
+ margin-top: spacing('4');
68
+ }
69
+ }
70
+
71
+ // Opt-in, because a single section on a legal page numbered "01" is noise.
72
+ // The browser counts, so no page keeps its own running order in the markup -
73
+ // and the number sits at the far end of the rule rather than above the title:
74
+ // the mark opens the line, the number closes it, and the title keeps the
75
+ // first thing read on the left.
76
+ .mw-section-head-numbered {
77
+ counter-increment: mw-section-head;
78
+
79
+ &::after {
80
+ content: counter(mw-section-head, decimal-leading-zero);
81
+ position: absolute;
82
+ top: var(--mw-section-head-pad);
83
+ right: 7px;
84
+ color: var(--mw-text-muted-color);
85
+ font-size: font-size('sm');
86
+ font-weight: font-weight('medium');
87
+ line-height: 1;
88
+ // The tracking sits after the last digit too, so it has to come back off
89
+ // the right or the number stands a space short of the edge it aligns to.
90
+ letter-spacing: 0.2em;
91
+ }
92
+
93
+ // The number owns the right end of the first line - a long title runs into
94
+ // it otherwise, and on a phone that is one word, not a rare case.
95
+ .mw-section-head-title {
96
+ padding-right: spacing('10');
97
+ }
47
98
  }
48
99
 
100
+ // The mark is the one coloured thing in the head, so it is where a section
101
+ // picks up a tone - a danger notice, a success story, a section that belongs
102
+ // to a product colour.
103
+ $_mw-section-head-colors: (secondary, success, warning, danger, info);
104
+
105
+ @each $name in $_mw-section-head-colors {
106
+ .mw-section-head-#{$name} {
107
+ --mw-section-head-mark-color: var(--mw-#{$name}-color);
108
+ }
109
+ }
110
+
111
+ // The level below the head: the boundary inside a section, not around it.
112
+ // Same left edge, and the rule shrinks to a mark of its own so the two
113
+ // levels read as a hierarchy rather than as two of the same thing.
49
114
  .mw-section-subtitle {
50
115
  font-size: fluid('xl', '2xl', $to: 'sm');
51
- // The step above a demo gap of spacing('6') - at spacing('8') the boundary
52
- // between two components read like the one between two demos
53
- margin: spacing('10') spacing('0') spacing('6') spacing('0');
54
- text-align: center;
116
+ // The section boundary is 56px on a phone, so the component boundary sits
117
+ // with it or the two stop being distinguishable
118
+ margin: spacing('6') spacing('0') spacing('4') spacing('0');
55
119
  position: relative;
56
120
 
57
- @include _section-rule(
58
- 32px,
59
- 2px,
60
- spacing('-2'),
61
- var(--mw-secondary-text-color)
62
- );
121
+ &::after {
122
+ content: '';
123
+ position: absolute;
124
+ bottom: spacing('-2');
125
+ left: 0;
126
+ width: 32px;
127
+ height: 2px;
128
+ border-radius: radius('xs');
129
+ background: var(--mw-secondary-text-color);
130
+ }
63
131
  }
64
132
 
65
133
  // Sticky, because the strip is the only way back: inside a long section the
@@ -131,11 +199,13 @@
131
199
  }
132
200
  }
133
201
 
134
- @include media-down('sm') {
135
- // The section boundary steps down to 56px on a phone, so the component
136
- // boundary steps with it or the two stop being distinguishable
202
+ @include media-up('sm') {
203
+ // One step above the demo gap of spacing('6'), and that step is the whole
204
+ // margin the boundary between two components has over the one between two
205
+ // demos - the heading leans toward what it names, not toward what came
206
+ // before it.
137
207
  .mw-section-subtitle {
138
- margin-top: spacing('7');
208
+ margin-top: spacing('8');
139
209
  }
140
210
  }
141
211
 
@@ -0,0 +1,16 @@
1
+ // The same framework without the 48 components: tokens, reset, typography,
2
+ // grid, container, section, header, footer and every utility. Add the
3
+ // components the page actually uses next to it, each one its own file:
4
+ //
5
+ // @use 'maverick-wave/src/scss/main-lean' with ($primary-color: #1b1b1d);
6
+ // @use 'maverick-wave/src/scss/components/buttons';
7
+ // @use 'maverick-wave/src/scss/components/cards';
8
+ //
9
+ // The configuration goes on this file, not on the component imports - they
10
+ // read the tokens it forwards. A landing page that uses eight components lands
11
+ // around a third of the full build; the components carry the rest.
12
+ @forward 'abstracts/variables';
13
+
14
+ @use 'base';
15
+ @use 'layout';
16
+ @use 'utilities';
@@ -4,6 +4,7 @@
4
4
  @forward 'display';
5
5
  @forward 'elevation';
6
6
  @forward 'flex';
7
+ @forward 'print';
7
8
  @forward 'reveal';
8
9
  @forward 'spacing';
9
10
  @forward 'text';
@@ -0,0 +1,107 @@
1
+ @use '../abstracts' as *;
2
+
3
+ // Last layer on purpose: these rules have to win against the components they
4
+ // flatten, and a media query adds no specificity of its own.
5
+ @layer mw.utilities {
6
+ // Hidden on screen, shown on paper. Before the print block and not after it:
7
+ // both rules have the same specificity, so the later one would win in print
8
+ // too and the note would never appear.
9
+ .mw-print-only {
10
+ display: none;
11
+ }
12
+
13
+ @media print {
14
+ // Paper is white and ink is black, whatever the screen was told to be. The
15
+ // tokens are redeclared on .mw-theme-light too - that copy sits further
16
+ // down the tree and would otherwise shadow the one on :root.
17
+ :root,
18
+ .mw-theme-light {
19
+ --mw-page-background: #fff;
20
+ --mw-card-background: #fff;
21
+ --mw-footer-background: #fff;
22
+ --mw-text-color: #000;
23
+ --mw-text-muted-color: #333;
24
+ --mw-border: #999;
25
+ --mw-border-accent: #666;
26
+
27
+ // No toner for depth that paper cannot show anyway. Level 0 is not in the
28
+ // list: it is flat by definition and nothing reads it as a variable.
29
+ --mw-elevation-1: none;
30
+ --mw-elevation-2: none;
31
+ --mw-elevation-3: none;
32
+ --mw-elevation-4: none;
33
+ --mw-elevation-5: none;
34
+ }
35
+
36
+ body {
37
+ background: #fff;
38
+ color: #000;
39
+ }
40
+
41
+ // Chrome that is fixed on screen would print on the first page and cover
42
+ // what is underneath, and navigation is useless on paper either way.
43
+ .mw-header,
44
+ .mw-announcement:not(.mw-announcement-static),
45
+ .mw-section-nav,
46
+ .mw-scroll-hint,
47
+ .mw-menu-btn,
48
+ .mw-theme-toggle,
49
+ .mw-skip-link,
50
+ .mw-toast-stack,
51
+ .mw-hide-print {
52
+ display: none;
53
+ }
54
+
55
+ // The counterpart: a note that only makes sense on the printed page
56
+ .mw-print-only {
57
+ display: revert;
58
+ }
59
+
60
+ // A surface without its tone still needs an edge to be a surface
61
+ .mw-card,
62
+ .mw-panel,
63
+ .mw-tile,
64
+ .mw-alert,
65
+ .mw-info {
66
+ border: 1px solid #999;
67
+ background: #fff;
68
+ }
69
+
70
+ // Anything that is one thing should not be torn across two pages
71
+ .mw-card,
72
+ .mw-panel,
73
+ .mw-tile,
74
+ .mw-section-head,
75
+ .mw-leader-row,
76
+ .mw-item-list-item,
77
+ tr,
78
+ figure,
79
+ blockquote {
80
+ break-inside: avoid;
81
+ }
82
+
83
+ // A heading at the foot of a page belongs to the next one
84
+ h1,
85
+ h2,
86
+ h3,
87
+ .mw-section-head-title,
88
+ .mw-section-subtitle {
89
+ break-after: avoid;
90
+ }
91
+
92
+ // Screen rhythm is scroll distance; on paper it is wasted sheets
93
+ .mw-section {
94
+ padding-block: spacing('6');
95
+ }
96
+
97
+ // A link is only worth printing when its target comes with it. Internal
98
+ // anchors and mail links stay quiet - the first says nothing on paper, the
99
+ // second already shows the address as its text.
100
+ .mw-prose a[href^='http']::after,
101
+ .mw-disclaimer a[href^='http']::after {
102
+ content: ' (' attr(href) ')';
103
+ font-size: font-size('xs');
104
+ word-break: break-all;
105
+ }
106
+ }
107
+ }