@aitrien/motifspec 1.13.0 → 1.13.2
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/CHANGELOG.md +269 -257
- package/LICENSE +21 -21
- package/README.md +150 -150
- package/dist/backdrop.html +1 -1
- package/dist/chroma.css +36 -36
- package/dist/codex.css +1145 -1145
- package/dist/codex.js +126 -126
- package/dist/contrast.md +101 -101
- package/dist/fonts.css +3 -3
- package/dist/icons.svg +18 -18
- package/dist/plate.html +1 -1
- package/dist/plate.js +292 -292
- package/dist/theme-init.js +1 -1
- package/dist/tokens.css +466 -466
- package/dist/tokens.js +3330 -3330
- package/dist/tokens.json +3330 -3330
- package/docs/components/_template.md +37 -37
- package/docs/components/accession-label.md +106 -106
- package/docs/components/backdrop.md +83 -83
- package/docs/components/button-and-link.md +87 -87
- package/docs/components/callout.md +75 -75
- package/docs/components/code-block.md +109 -109
- package/docs/components/data-table.md +73 -73
- package/docs/components/figure.md +68 -68
- package/docs/components/heading-anchor.md +76 -76
- package/docs/components/icon.md +63 -63
- package/docs/components/ornament.md +77 -77
- package/docs/components/pagination.md +78 -78
- package/docs/components/post-list-item.md +91 -91
- package/docs/components/project-card.md +82 -82
- package/docs/components/prose.md +122 -122
- package/docs/components/site-footer.md +99 -99
- package/docs/components/site-header.md +133 -133
- package/docs/components/specimen-plate.md +92 -92
- package/docs/components/table-of-contents.md +83 -83
- package/docs/components/tag.md +70 -70
- package/docs/components/tooltip.md +67 -67
- package/docs/hugo.md +120 -120
- package/docs/syntax-highlighting.md +55 -55
- package/docs/templates.md +30 -30
- package/fonts/OFL-jetbrains-mono.txt +93 -93
- package/fonts/OFL-national-park.txt +93 -93
- package/fonts/OFL-yarndings-12.txt +93 -93
- package/icons/LICENSE +202 -202
- package/icons/manifest.json +75 -75
- package/layouts/_markup/render-blockquote.html +30 -30
- package/layouts/_markup/render-codeblock.html +18 -18
- package/layouts/_markup/render-heading.html +2 -2
- package/layouts/_markup/render-image.html +14 -14
- package/layouts/_markup/render-link.html +14 -14
- package/layouts/_markup/render-table.html +31 -31
- package/layouts/_partials/motifspec/accession/id.html +2 -2
- package/layouts/_partials/motifspec/accession/label.html +18 -18
- package/layouts/_partials/motifspec/accession/status.html +2 -2
- package/layouts/_partials/motifspec/article.html +24 -24
- package/layouts/_partials/motifspec/back-link.html +2 -2
- package/layouts/_partials/motifspec/body-end.html +5 -5
- package/layouts/_partials/motifspec/body-start.html +5 -5
- package/layouts/_partials/motifspec/figure.html +14 -14
- package/layouts/_partials/motifspec/filed-under.html +5 -5
- package/layouts/_partials/motifspec/h2s.html +7 -7
- package/layouts/_partials/motifspec/head.html +15 -15
- package/layouts/_partials/motifspec/pagination-entries.html +34 -34
- package/layouts/_partials/motifspec/pagination-pages.html +30 -30
- package/layouts/_partials/motifspec/post-list-item.html +15 -15
- package/layouts/_partials/motifspec/project-card.html +23 -23
- package/layouts/_partials/motifspec/section-heading.html +3 -3
- package/layouts/_partials/motifspec/site-header.html +27 -27
- package/layouts/_partials/motifspec/table-of-contents.html +21 -21
- package/layouts/_partials/motifspec/tag-filter.html +22 -22
- package/layouts/_partials/motifspec/tags.html +8 -8
- package/layouts/_partials/motifspec/tokens.html +9 -9
- package/package.json +68 -68
- package/scripts/check.mjs +153 -153
- package/scripts/lib.mjs +176 -176
- package/tokens/README.md +3 -3
- package/tokens/border.json +63 -63
- package/tokens/color.json +1902 -1902
- package/tokens/motion.json +207 -207
- package/tokens/radius.json +53 -53
- package/tokens/size.json +378 -378
- package/tokens/space.json +289 -289
- package/tokens/typography.json +859 -859
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: component-name
|
|
3
|
-
status: draft # draft | stable | deprecated
|
|
4
|
-
tokens: # semantic tokens this component uses
|
|
5
|
-
- color.accent
|
|
6
|
-
- space.md
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Component name
|
|
10
|
-
|
|
11
|
-
One sentence: what it is for.
|
|
12
|
-
|
|
13
|
-
## When to use
|
|
14
|
-
|
|
15
|
-
- …
|
|
16
|
-
|
|
17
|
-
## When not to use
|
|
18
|
-
|
|
19
|
-
- …
|
|
20
|
-
|
|
21
|
-
## Markup
|
|
22
|
-
|
|
23
|
-
```html preview
|
|
24
|
-
<!-- Minimal markup. The dashboard renders this block as a live preview, and the MCP server returns it as the pattern to copy. -->
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Do
|
|
28
|
-
|
|
29
|
-
- …
|
|
30
|
-
|
|
31
|
-
## Don't
|
|
32
|
-
|
|
33
|
-
- …
|
|
34
|
-
|
|
35
|
-
## Accessibility
|
|
36
|
-
|
|
37
|
-
- Keyboard behaviour, roles, contrast pairs.
|
|
1
|
+
---
|
|
2
|
+
name: component-name
|
|
3
|
+
status: draft # draft | stable | deprecated
|
|
4
|
+
tokens: # semantic tokens this component uses
|
|
5
|
+
- color.accent
|
|
6
|
+
- space.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Component name
|
|
10
|
+
|
|
11
|
+
One sentence: what it is for.
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
|
|
15
|
+
- …
|
|
16
|
+
|
|
17
|
+
## When not to use
|
|
18
|
+
|
|
19
|
+
- …
|
|
20
|
+
|
|
21
|
+
## Markup
|
|
22
|
+
|
|
23
|
+
```html preview
|
|
24
|
+
<!-- Minimal markup. The dashboard renders this block as a live preview, and the MCP server returns it as the pattern to copy. -->
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Do
|
|
28
|
+
|
|
29
|
+
- …
|
|
30
|
+
|
|
31
|
+
## Don't
|
|
32
|
+
|
|
33
|
+
- …
|
|
34
|
+
|
|
35
|
+
## Accessibility
|
|
36
|
+
|
|
37
|
+
- Keyboard behaviour, roles, contrast pairs.
|
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: accession-label
|
|
3
|
-
status: stable
|
|
4
|
-
tokens:
|
|
5
|
-
- border.width.hairline
|
|
6
|
-
- color.border.default
|
|
7
|
-
- color.border.subtle
|
|
8
|
-
- color.link.rest
|
|
9
|
-
- color.ornament.muted
|
|
10
|
-
- color.status.success.text
|
|
11
|
-
- color.status.warning.text
|
|
12
|
-
- color.surface.raised
|
|
13
|
-
- color.text.accent
|
|
14
|
-
- color.text.muted
|
|
15
|
-
- color.text.primary
|
|
16
|
-
- font.family.mono
|
|
17
|
-
- font.line-height.ui
|
|
18
|
-
- font.size.label
|
|
19
|
-
- font.tracking.label
|
|
20
|
-
- font.tracking.ui
|
|
21
|
-
- font.weight.ui
|
|
22
|
-
- radius.round
|
|
23
|
-
- size.mark.tick
|
|
24
|
-
- space.inline.sm
|
|
25
|
-
- space.inline.xs
|
|
26
|
-
- space.inset.md
|
|
27
|
-
- space.inset.sm
|
|
28
|
-
- space.stack.xs
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
# Accession label
|
|
32
|
-
|
|
33
|
-
The system's signature: a herbarium-style label that gives an entry its catalogue number and key facts, framed by registration ticks.
|
|
34
|
-
|
|
35
|
-
## When to use
|
|
36
|
-
|
|
37
|
-
- At the top of a project case study (full label) and on a 404 ("No. — / Not in collection").
|
|
38
|
-
- In compact form (`.cx-id`) on project cards, post rows and post meta lines.
|
|
39
|
-
- Wherever an entry needs a stable, citable identifier.
|
|
40
|
-
|
|
41
|
-
## When not to use
|
|
42
|
-
|
|
43
|
-
- For decorative badges or skill lists; use `tag`.
|
|
44
|
-
- For more than six fields. Move the rest into the prose.
|
|
45
|
-
- On pages that are not catalogued entries (home, indexes).
|
|
46
|
-
|
|
47
|
-
## Catalogue numbers
|
|
48
|
-
|
|
49
|
-
`LM-{collection}-{sequence}`, with the sequence zero-padded to three digits and never reused.
|
|
50
|
-
|
|
51
|
-
| Collection | Code | Example |
|
|
52
|
-
|---|---|---|
|
|
53
|
-
| Work (projects, case studies) | `W` | `LM-W-004` |
|
|
54
|
-
| Writing (posts) | `P` | `LM-P-031` |
|
|
55
|
-
|
|
56
|
-
Store the number in front matter (`accession: LM-W-004`) rather than deriving it from the date or slug, so it survives renames.
|
|
57
|
-
|
|
58
|
-
## Markup
|
|
59
|
-
|
|
60
|
-
```html preview
|
|
61
|
-
<dl class="cx-label" aria-label="Accession label">
|
|
62
|
-
<div class="cx-label__id"><dt>No.</dt><dd>LM-W-001</dd></div>
|
|
63
|
-
<div><dt>Filed</dt><dd><time datetime="2026-03-14">2026-03-14</time></dd></div>
|
|
64
|
-
<div><dt>Role</dt><dd>Sole engineer</dd></div>
|
|
65
|
-
<div><dt>Stack</dt><dd>React <span class="cx-sep" aria-hidden="true">|</span> WebGL <span class="cx-sep" aria-hidden="true">|</span> Vite</dd></div>
|
|
66
|
-
<div><dt>Status</dt><dd><span class="cx-status cx-status--live">Live</span></dd></div>
|
|
67
|
-
</dl>
|
|
68
|
-
|
|
69
|
-
<!-- On a case study: the lead label above the title and the card after the article. Role and stack are
|
|
70
|
-
cx-label__detail fields; below size.breakpoint.md the lead label hides them and the card shows everything. -->
|
|
71
|
-
<dl class="cx-label cx-label--lead" aria-label="Accession label">
|
|
72
|
-
<div class="cx-label__id"><dt>No.</dt><dd>LM-W-001</dd></div>
|
|
73
|
-
<div><dt>Filed</dt><dd><time datetime="2026-03-14">2026-03-14</time></dd></div>
|
|
74
|
-
<div class="cx-label__detail"><dt>Role</dt><dd>Sole engineer</dd></div>
|
|
75
|
-
<div class="cx-label__detail"><dt>Stack</dt><dd>React <span class="cx-sep" aria-hidden="true">|</span> WebGL <span class="cx-sep" aria-hidden="true">|</span> Vite</dd></div>
|
|
76
|
-
<div><dt>Status</dt><dd><span class="cx-status cx-status--live">Live</span></dd></div>
|
|
77
|
-
</dl>
|
|
78
|
-
<!-- … the article … -->
|
|
79
|
-
<dl class="cx-label cx-label--card" aria-label="Accession label"><!-- the same five fields, no __detail classes --></dl>
|
|
80
|
-
|
|
81
|
-
<!-- Compact form -->
|
|
82
|
-
<p class="cx-id"><span class="cx-id__no">LM-P-031</span><time datetime="2026-10-02">2026-10-02</time><span>6 min read</span></p>
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Do
|
|
86
|
-
|
|
87
|
-
- Put the number first, then the date, then everything else.
|
|
88
|
-
- Use ISO dates (`2026-03-14`) in tabular figures.
|
|
89
|
-
- Separate items inside a field with `cx-sep` (a hidden "|"). The compact form adds its own "|" between items.
|
|
90
|
-
- Use `cx-status--live`, `--building` or `--archived`; each pairs a dot with a word.
|
|
91
|
-
- On a case study, pair a lead label (`cx-label--lead`) above the title with a card (`cx-label--card`) after the article, holding the same fields. Below `size.breakpoint.md` the lead label shows only the number, date and status, because role and stack are marked `cx-label__detail`, and the card shows the full label at the end. From `size.breakpoint.md` up the lead label is complete and the card is hidden. Only one of the two is ever complete on screen.
|
|
92
|
-
- Let the fields wrap. Each field grows to fill its row and carries a `color.border.subtle` rule on its right and below, so a label that wraps onto several rows reads as a ruled grid, with every row closed by a full-width rule; the frame stays `color.border.default`.
|
|
93
|
-
|
|
94
|
-
## Don't
|
|
95
|
-
|
|
96
|
-
- Don't use more than one full label per page. The lead label and its card count as one: at any width, only one of them shows role and stack.
|
|
97
|
-
- Don't put links to unrelated pages in the label; it describes the entry.
|
|
98
|
-
- Don't recolour the ticks or use them on other components except the specimen plate.
|
|
99
|
-
|
|
100
|
-
## Accessibility
|
|
101
|
-
|
|
102
|
-
- `<dl>` with `<dt>`/`<dd>` pairs is read as name–value pairs. Give the list `aria-label="Accession label"`.
|
|
103
|
-
- Hidden fields and the hidden card use `display: none`, so assistive tech reads the same fields a sighted reader sees: on a phone, number, date and status at the top and the whole label after the article.
|
|
104
|
-
- Status is a word plus a dot, never colour alone.
|
|
105
|
-
- The ticks are a background on a pseudo-element and are invisible to assistive tech.
|
|
106
|
-
- Pairs: `color.text.accent` on `color.surface.raised` (4.5:1); `color.text.muted` on `color.surface.raised` (4.5:1); `color.status.*.text` on `color.surface.raised` (4.5:1).
|
|
1
|
+
---
|
|
2
|
+
name: accession-label
|
|
3
|
+
status: stable
|
|
4
|
+
tokens:
|
|
5
|
+
- border.width.hairline
|
|
6
|
+
- color.border.default
|
|
7
|
+
- color.border.subtle
|
|
8
|
+
- color.link.rest
|
|
9
|
+
- color.ornament.muted
|
|
10
|
+
- color.status.success.text
|
|
11
|
+
- color.status.warning.text
|
|
12
|
+
- color.surface.raised
|
|
13
|
+
- color.text.accent
|
|
14
|
+
- color.text.muted
|
|
15
|
+
- color.text.primary
|
|
16
|
+
- font.family.mono
|
|
17
|
+
- font.line-height.ui
|
|
18
|
+
- font.size.label
|
|
19
|
+
- font.tracking.label
|
|
20
|
+
- font.tracking.ui
|
|
21
|
+
- font.weight.ui
|
|
22
|
+
- radius.round
|
|
23
|
+
- size.mark.tick
|
|
24
|
+
- space.inline.sm
|
|
25
|
+
- space.inline.xs
|
|
26
|
+
- space.inset.md
|
|
27
|
+
- space.inset.sm
|
|
28
|
+
- space.stack.xs
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
# Accession label
|
|
32
|
+
|
|
33
|
+
The system's signature: a herbarium-style label that gives an entry its catalogue number and key facts, framed by registration ticks.
|
|
34
|
+
|
|
35
|
+
## When to use
|
|
36
|
+
|
|
37
|
+
- At the top of a project case study (full label) and on a 404 ("No. — / Not in collection").
|
|
38
|
+
- In compact form (`.cx-id`) on project cards, post rows and post meta lines.
|
|
39
|
+
- Wherever an entry needs a stable, citable identifier.
|
|
40
|
+
|
|
41
|
+
## When not to use
|
|
42
|
+
|
|
43
|
+
- For decorative badges or skill lists; use `tag`.
|
|
44
|
+
- For more than six fields. Move the rest into the prose.
|
|
45
|
+
- On pages that are not catalogued entries (home, indexes).
|
|
46
|
+
|
|
47
|
+
## Catalogue numbers
|
|
48
|
+
|
|
49
|
+
`LM-{collection}-{sequence}`, with the sequence zero-padded to three digits and never reused.
|
|
50
|
+
|
|
51
|
+
| Collection | Code | Example |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| Work (projects, case studies) | `W` | `LM-W-004` |
|
|
54
|
+
| Writing (posts) | `P` | `LM-P-031` |
|
|
55
|
+
|
|
56
|
+
Store the number in front matter (`accession: LM-W-004`) rather than deriving it from the date or slug, so it survives renames.
|
|
57
|
+
|
|
58
|
+
## Markup
|
|
59
|
+
|
|
60
|
+
```html preview
|
|
61
|
+
<dl class="cx-label" aria-label="Accession label">
|
|
62
|
+
<div class="cx-label__id"><dt>No.</dt><dd>LM-W-001</dd></div>
|
|
63
|
+
<div><dt>Filed</dt><dd><time datetime="2026-03-14">2026-03-14</time></dd></div>
|
|
64
|
+
<div><dt>Role</dt><dd>Sole engineer</dd></div>
|
|
65
|
+
<div><dt>Stack</dt><dd>React <span class="cx-sep" aria-hidden="true">|</span> WebGL <span class="cx-sep" aria-hidden="true">|</span> Vite</dd></div>
|
|
66
|
+
<div><dt>Status</dt><dd><span class="cx-status cx-status--live">Live</span></dd></div>
|
|
67
|
+
</dl>
|
|
68
|
+
|
|
69
|
+
<!-- On a case study: the lead label above the title and the card after the article. Role and stack are
|
|
70
|
+
cx-label__detail fields; below size.breakpoint.md the lead label hides them and the card shows everything. -->
|
|
71
|
+
<dl class="cx-label cx-label--lead" aria-label="Accession label">
|
|
72
|
+
<div class="cx-label__id"><dt>No.</dt><dd>LM-W-001</dd></div>
|
|
73
|
+
<div><dt>Filed</dt><dd><time datetime="2026-03-14">2026-03-14</time></dd></div>
|
|
74
|
+
<div class="cx-label__detail"><dt>Role</dt><dd>Sole engineer</dd></div>
|
|
75
|
+
<div class="cx-label__detail"><dt>Stack</dt><dd>React <span class="cx-sep" aria-hidden="true">|</span> WebGL <span class="cx-sep" aria-hidden="true">|</span> Vite</dd></div>
|
|
76
|
+
<div><dt>Status</dt><dd><span class="cx-status cx-status--live">Live</span></dd></div>
|
|
77
|
+
</dl>
|
|
78
|
+
<!-- … the article … -->
|
|
79
|
+
<dl class="cx-label cx-label--card" aria-label="Accession label"><!-- the same five fields, no __detail classes --></dl>
|
|
80
|
+
|
|
81
|
+
<!-- Compact form -->
|
|
82
|
+
<p class="cx-id"><span class="cx-id__no">LM-P-031</span><time datetime="2026-10-02">2026-10-02</time><span>6 min read</span></p>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Do
|
|
86
|
+
|
|
87
|
+
- Put the number first, then the date, then everything else.
|
|
88
|
+
- Use ISO dates (`2026-03-14`) in tabular figures.
|
|
89
|
+
- Separate items inside a field with `cx-sep` (a hidden "|"). The compact form adds its own "|" between items.
|
|
90
|
+
- Use `cx-status--live`, `--building` or `--archived`; each pairs a dot with a word.
|
|
91
|
+
- On a case study, pair a lead label (`cx-label--lead`) above the title with a card (`cx-label--card`) after the article, holding the same fields. Below `size.breakpoint.md` the lead label shows only the number, date and status, because role and stack are marked `cx-label__detail`, and the card shows the full label at the end. From `size.breakpoint.md` up the lead label is complete and the card is hidden. Only one of the two is ever complete on screen.
|
|
92
|
+
- Let the fields wrap. Each field grows to fill its row and carries a `color.border.subtle` rule on its right and below, so a label that wraps onto several rows reads as a ruled grid, with every row closed by a full-width rule; the frame stays `color.border.default`.
|
|
93
|
+
|
|
94
|
+
## Don't
|
|
95
|
+
|
|
96
|
+
- Don't use more than one full label per page. The lead label and its card count as one: at any width, only one of them shows role and stack.
|
|
97
|
+
- Don't put links to unrelated pages in the label; it describes the entry.
|
|
98
|
+
- Don't recolour the ticks or use them on other components except the specimen plate.
|
|
99
|
+
|
|
100
|
+
## Accessibility
|
|
101
|
+
|
|
102
|
+
- `<dl>` with `<dt>`/`<dd>` pairs is read as name–value pairs. Give the list `aria-label="Accession label"`.
|
|
103
|
+
- Hidden fields and the hidden card use `display: none`, so assistive tech reads the same fields a sighted reader sees: on a phone, number, date and status at the top and the whole label after the article.
|
|
104
|
+
- Status is a word plus a dot, never colour alone.
|
|
105
|
+
- The ticks are a background on a pseudo-element and are invisible to assistive tech.
|
|
106
|
+
- Pairs: `color.text.accent` on `color.surface.raised` (4.5:1); `color.text.muted` on `color.surface.raised` (4.5:1); `color.status.*.text` on `color.surface.raised` (4.5:1).
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: backdrop
|
|
3
|
-
status: stable
|
|
4
|
-
tokens:
|
|
5
|
-
- border.focus.offset
|
|
6
|
-
- border.focus.width
|
|
7
|
-
- border.width.contour
|
|
8
|
-
- color.backdrop.grain
|
|
9
|
-
- color.backdrop.saturation
|
|
10
|
-
- color.backdrop.tint
|
|
11
|
-
- color.focus.ring
|
|
12
|
-
- color.surface.base
|
|
13
|
-
- color.text.primary
|
|
14
|
-
- color.text.secondary
|
|
15
|
-
- motion.duration.drift
|
|
16
|
-
- motion.duration.fast
|
|
17
|
-
- motion.duration.plate
|
|
18
|
-
- motion.duration.slow
|
|
19
|
-
- motion.easing.standard
|
|
20
|
-
- radius.pill
|
|
21
|
-
- size.backdrop.blur
|
|
22
|
-
- size.backdrop.fade
|
|
23
|
-
- size.backdrop.height
|
|
24
|
-
- size.target.touch
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
# Backdrop
|
|
28
|
-
|
|
29
|
-
The contour survey drawn full-bleed behind every page, under a grainy frost. The page's own surface fades out over its first and last `size.backdrop.fade`, so the frost shows behind the header and footer and reading happens on the plain surface.
|
|
30
|
-
|
|
31
|
-
## When to use
|
|
32
|
-
|
|
33
|
-
- On every page of a site built from the system, in all six templates (`templates.md`), 404 included.
|
|
34
|
-
- Once per page: one `cx-backdrop`, the first child of `<body class="cx-backdrop-page">`.
|
|
35
|
-
- With the backdrop pause control in the header (`site-header.md`), because the terrain drifts.
|
|
36
|
-
|
|
37
|
-
## When not to use
|
|
38
|
-
|
|
39
|
-
- On the same page as the specimen plate: one contour field per page. The showcase, which documents both, is the only exception.
|
|
40
|
-
- Inside a component or as a section background. The frost is one layer for the whole page.
|
|
41
|
-
- Behind layouts that need the plain surface from the very top, such as a full-screen app or a print stylesheet.
|
|
42
|
-
|
|
43
|
-
## Markup
|
|
44
|
-
|
|
45
|
-
The build writes the backdrop to `dist/backdrop.html` (the contours at time zero, sliced to cover the viewport). In Hugo, inline it first in `<body>` and load `dist/plate.js`, which drifts it:
|
|
46
|
-
|
|
47
|
-
```html preview
|
|
48
|
-
<body class="cx-backdrop-page">
|
|
49
|
-
{{ (resources.Get "motifspec/backdrop.html").Content | safeHTML }}
|
|
50
|
-
<!-- <div class="cx-backdrop" aria-hidden="true" data-plate-seed="3"><svg class="cx-plate__map" preserveAspectRatio="xMidYMid slice" …>…</svg></div> -->
|
|
51
|
-
<a class="cx-skip-link" href="#main">Skip to content</a>
|
|
52
|
-
<header class="cx-header"><!-- site-header.md, with the backdrop pause control --></header>
|
|
53
|
-
<main id="main"><!-- the template --></main>
|
|
54
|
-
<footer class="cx-footer"><!-- site-footer.md --></footer>
|
|
55
|
-
<script src="{{ (resources.Get "motifspec/plate.js" | minify | fingerprint).RelPermalink }}" defer></script>
|
|
56
|
-
</body>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
From the bottom up: the canvas (`color.surface.base`), the contours (the specimen plate's `color.ornament.rest` lines and `color.ornament.strong` index contours, at `border.width.contour` and twice that, blurred by `size.backdrop.blur` and `color.backdrop.saturation`), the frost (`color.backdrop.tint` of the surface), the grain (monochrome noise at `color.backdrop.grain`), then the page, whose surface is solid between the two fades.
|
|
60
|
-
|
|
61
|
-
## Do
|
|
62
|
-
|
|
63
|
-
- Load `dist/plate.js` on every page that has the backdrop. It starts the drift as soon as it runs, easing up from rest over `motion.duration.plate` rather than jumping to full speed (and again whenever the drift resumes), and reveals the header's pause control; without it the contours stay still and the control stays hidden.
|
|
64
|
-
- Let the header and footer sit on the frost. `cx-backdrop-page` removes their surfaces. Once the page scrolls, `dist/codex.js` makes the header sticky and fades its surface back in, so it never sits see-through on the text below; back at the top it returns to the frost (`site-header.md`). Without the script it scrolls away with the page.
|
|
65
|
-
- Keep the layer's height at `size.backdrop.height`, the large viewport (`lvh`). On a phone the address bar slides away as you scroll; a layer pinned to the bottom of the screen, or sized in `dvh` or `svh`, resizes with it, re-fits the contours and makes them jump.
|
|
66
|
-
- Tune the look through the backdrop tokens only.
|
|
67
|
-
- Keep the opening statement inside the top fade, so it is the one piece of content that sits on the frost.
|
|
68
|
-
|
|
69
|
-
## Don't
|
|
70
|
-
|
|
71
|
-
- Don't give sections, panels or cards a frosted background of their own.
|
|
72
|
-
- Don't position `<body>` or give it a `z-index`. The backdrop paints at `z-index: -1` in the root stacking context, under the page's own surface.
|
|
73
|
-
- Don't raise `color.backdrop.grain` until the noise competes with text.
|
|
74
|
-
- Don't switch the blur to `backdrop-filter`. Chromium blurs only what is on screen, so lines crossing the viewport edge stay sharp there; the CSS `filter` on the contours, over a layer that reaches past the edge, does not. Don't give the grain a `mix-blend-mode` either: in Chromium it brought sharp lines back.
|
|
75
|
-
- Don't put text, links or controls in the backdrop.
|
|
76
|
-
|
|
77
|
-
## Accessibility
|
|
78
|
-
|
|
79
|
-
- The backdrop is `aria-hidden` and carries no information.
|
|
80
|
-
- WCAG 2.2.2 (Pause, Stop, Hide): the drift runs longer than five seconds, so the header's pause control (a native checkbox named "Pause background animation"; checked means paused) stops it. It ships `hidden`; the script reveals it when the drift starts. The choice persists across pages, like the theme: it is stored as `paused` under the `cx-backdrop` key and restored before the drift starts, so a paused backdrop never moves on the next page. If storage is blocked, the pause still applies to the current page. The drift also stops off screen and in hidden tabs.
|
|
81
|
-
- Under `prefers-reduced-motion: reduce` the contours never move and the pause control stays hidden.
|
|
82
|
-
- Reading text below the top fade sits on `color.surface.base`, so the declared pairs apply. Text over the frost (the header, the footer, the opening of a page, and all of a short page) is measured against `color.surface.base` too: by design, contrast is not checked against the blurred contour lines beneath it.
|
|
83
|
-
- The blur is a CSS `filter`, supported everywhere the rest of the system is, so contrast never depends on `backdrop-filter` support.
|
|
1
|
+
---
|
|
2
|
+
name: backdrop
|
|
3
|
+
status: stable
|
|
4
|
+
tokens:
|
|
5
|
+
- border.focus.offset
|
|
6
|
+
- border.focus.width
|
|
7
|
+
- border.width.contour
|
|
8
|
+
- color.backdrop.grain
|
|
9
|
+
- color.backdrop.saturation
|
|
10
|
+
- color.backdrop.tint
|
|
11
|
+
- color.focus.ring
|
|
12
|
+
- color.surface.base
|
|
13
|
+
- color.text.primary
|
|
14
|
+
- color.text.secondary
|
|
15
|
+
- motion.duration.drift
|
|
16
|
+
- motion.duration.fast
|
|
17
|
+
- motion.duration.plate
|
|
18
|
+
- motion.duration.slow
|
|
19
|
+
- motion.easing.standard
|
|
20
|
+
- radius.pill
|
|
21
|
+
- size.backdrop.blur
|
|
22
|
+
- size.backdrop.fade
|
|
23
|
+
- size.backdrop.height
|
|
24
|
+
- size.target.touch
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Backdrop
|
|
28
|
+
|
|
29
|
+
The contour survey drawn full-bleed behind every page, under a grainy frost. The page's own surface fades out over its first and last `size.backdrop.fade`, so the frost shows behind the header and footer and reading happens on the plain surface.
|
|
30
|
+
|
|
31
|
+
## When to use
|
|
32
|
+
|
|
33
|
+
- On every page of a site built from the system, in all six templates (`templates.md`), 404 included.
|
|
34
|
+
- Once per page: one `cx-backdrop`, the first child of `<body class="cx-backdrop-page">`.
|
|
35
|
+
- With the backdrop pause control in the header (`site-header.md`), because the terrain drifts.
|
|
36
|
+
|
|
37
|
+
## When not to use
|
|
38
|
+
|
|
39
|
+
- On the same page as the specimen plate: one contour field per page. The showcase, which documents both, is the only exception.
|
|
40
|
+
- Inside a component or as a section background. The frost is one layer for the whole page.
|
|
41
|
+
- Behind layouts that need the plain surface from the very top, such as a full-screen app or a print stylesheet.
|
|
42
|
+
|
|
43
|
+
## Markup
|
|
44
|
+
|
|
45
|
+
The build writes the backdrop to `dist/backdrop.html` (the contours at time zero, sliced to cover the viewport). In Hugo, inline it first in `<body>` and load `dist/plate.js`, which drifts it:
|
|
46
|
+
|
|
47
|
+
```html preview
|
|
48
|
+
<body class="cx-backdrop-page">
|
|
49
|
+
{{ (resources.Get "motifspec/backdrop.html").Content | safeHTML }}
|
|
50
|
+
<!-- <div class="cx-backdrop" aria-hidden="true" data-plate-seed="3"><svg class="cx-plate__map" preserveAspectRatio="xMidYMid slice" …>…</svg></div> -->
|
|
51
|
+
<a class="cx-skip-link" href="#main">Skip to content</a>
|
|
52
|
+
<header class="cx-header"><!-- site-header.md, with the backdrop pause control --></header>
|
|
53
|
+
<main id="main"><!-- the template --></main>
|
|
54
|
+
<footer class="cx-footer"><!-- site-footer.md --></footer>
|
|
55
|
+
<script src="{{ (resources.Get "motifspec/plate.js" | minify | fingerprint).RelPermalink }}" defer></script>
|
|
56
|
+
</body>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
From the bottom up: the canvas (`color.surface.base`), the contours (the specimen plate's `color.ornament.rest` lines and `color.ornament.strong` index contours, at `border.width.contour` and twice that, blurred by `size.backdrop.blur` and `color.backdrop.saturation`), the frost (`color.backdrop.tint` of the surface), the grain (monochrome noise at `color.backdrop.grain`), then the page, whose surface is solid between the two fades.
|
|
60
|
+
|
|
61
|
+
## Do
|
|
62
|
+
|
|
63
|
+
- Load `dist/plate.js` on every page that has the backdrop. It starts the drift as soon as it runs, easing up from rest over `motion.duration.plate` rather than jumping to full speed (and again whenever the drift resumes), and reveals the header's pause control; without it the contours stay still and the control stays hidden.
|
|
64
|
+
- Let the header and footer sit on the frost. `cx-backdrop-page` removes their surfaces. Once the page scrolls, `dist/codex.js` makes the header sticky and fades its surface back in, so it never sits see-through on the text below; back at the top it returns to the frost (`site-header.md`). Without the script it scrolls away with the page.
|
|
65
|
+
- Keep the layer's height at `size.backdrop.height`, the large viewport (`lvh`). On a phone the address bar slides away as you scroll; a layer pinned to the bottom of the screen, or sized in `dvh` or `svh`, resizes with it, re-fits the contours and makes them jump.
|
|
66
|
+
- Tune the look through the backdrop tokens only.
|
|
67
|
+
- Keep the opening statement inside the top fade, so it is the one piece of content that sits on the frost.
|
|
68
|
+
|
|
69
|
+
## Don't
|
|
70
|
+
|
|
71
|
+
- Don't give sections, panels or cards a frosted background of their own.
|
|
72
|
+
- Don't position `<body>` or give it a `z-index`. The backdrop paints at `z-index: -1` in the root stacking context, under the page's own surface.
|
|
73
|
+
- Don't raise `color.backdrop.grain` until the noise competes with text.
|
|
74
|
+
- Don't switch the blur to `backdrop-filter`. Chromium blurs only what is on screen, so lines crossing the viewport edge stay sharp there; the CSS `filter` on the contours, over a layer that reaches past the edge, does not. Don't give the grain a `mix-blend-mode` either: in Chromium it brought sharp lines back.
|
|
75
|
+
- Don't put text, links or controls in the backdrop.
|
|
76
|
+
|
|
77
|
+
## Accessibility
|
|
78
|
+
|
|
79
|
+
- The backdrop is `aria-hidden` and carries no information.
|
|
80
|
+
- WCAG 2.2.2 (Pause, Stop, Hide): the drift runs longer than five seconds, so the header's pause control (a native checkbox named "Pause background animation"; checked means paused) stops it. It ships `hidden`; the script reveals it when the drift starts. The choice persists across pages, like the theme: it is stored as `paused` under the `cx-backdrop` key and restored before the drift starts, so a paused backdrop never moves on the next page. If storage is blocked, the pause still applies to the current page. The drift also stops off screen and in hidden tabs.
|
|
81
|
+
- Under `prefers-reduced-motion: reduce` the contours never move and the pause control stays hidden.
|
|
82
|
+
- Reading text below the top fade sits on `color.surface.base`, so the declared pairs apply. Text over the frost (the header, the footer, the opening of a page, and all of a short page) is measured against `color.surface.base` too: by design, contrast is not checked against the blurred contour lines beneath it.
|
|
83
|
+
- The blur is a CSS `filter`, supported everywhere the rest of the system is, so contrast never depends on `backdrop-filter` support.
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: button-and-link
|
|
3
|
-
status: stable
|
|
4
|
-
tokens:
|
|
5
|
-
- border.focus.offset
|
|
6
|
-
- border.focus.width
|
|
7
|
-
- border.width.emphasis
|
|
8
|
-
- border.width.hairline
|
|
9
|
-
- color.accent.fill.hover
|
|
10
|
-
- color.accent.fill.rest
|
|
11
|
-
- color.border.strong
|
|
12
|
-
- color.focus.ring
|
|
13
|
-
- color.link.hover
|
|
14
|
-
- color.link.rest
|
|
15
|
-
- color.surface.hover
|
|
16
|
-
- color.surface.raised
|
|
17
|
-
- color.text.muted
|
|
18
|
-
- color.text.on-accent
|
|
19
|
-
- color.text.primary
|
|
20
|
-
- font.family.body
|
|
21
|
-
- font.family.mono
|
|
22
|
-
- font.line-height.ui
|
|
23
|
-
- font.size.label
|
|
24
|
-
- font.size.small
|
|
25
|
-
- font.tracking.label
|
|
26
|
-
- font.weight.strong
|
|
27
|
-
- font.weight.ui
|
|
28
|
-
- motion.distance.nudge
|
|
29
|
-
- motion.duration.fast
|
|
30
|
-
- motion.easing.standard
|
|
31
|
-
- radius.pill
|
|
32
|
-
- size.target.control
|
|
33
|
-
- size.target.min
|
|
34
|
-
- space.inline.md
|
|
35
|
-
- space.inline.sm
|
|
36
|
-
- space.inline.xs
|
|
37
|
-
- space.inset.lg
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
# Button and link
|
|
41
|
-
|
|
42
|
-
Buttons start actions or journeys; standalone links and back links move between pages.
|
|
43
|
-
|
|
44
|
-
## When to use
|
|
45
|
-
|
|
46
|
-
- `cx-button--primary`: the one main action in a view ("View work").
|
|
47
|
-
- `cx-button`: a secondary action beside it.
|
|
48
|
-
- `cx-link`: a standalone forward link at the end of a section ("All projects" plus a forward arrow).
|
|
49
|
-
- `cx-back`: the return link at the top of a post or case study (back arrow plus "All writing").
|
|
50
|
-
|
|
51
|
-
## When not to use
|
|
52
|
-
|
|
53
|
-
- For inline links in text; `prose` styles those.
|
|
54
|
-
- Two primary buttons in one view. Make the second one secondary.
|
|
55
|
-
- For navigation between sibling posts; use `pagination`.
|
|
56
|
-
|
|
57
|
-
## Markup
|
|
58
|
-
|
|
59
|
-
```html preview
|
|
60
|
-
<div class="cx-actions">
|
|
61
|
-
<a class="cx-button cx-button--primary" href="/work/">View work <svg class="cx-icon cx-button__arrow" aria-hidden="true" focusable="false"><use href="#cx-icon-arrow-forward"></use></svg></a>
|
|
62
|
-
<a class="cx-button" href="/writing/">Read the writing</a>
|
|
63
|
-
<button class="cx-button" type="button" disabled>Not yet published</button>
|
|
64
|
-
</div>
|
|
65
|
-
<a class="cx-link" href="/work/">All projects <svg class="cx-icon cx-button__arrow" aria-hidden="true" focusable="false"><use href="#cx-icon-arrow-forward"></use></svg></a>
|
|
66
|
-
<a class="cx-back" href="/writing/"><svg class="cx-icon cx-icon--sm cx-button__arrow" aria-hidden="true" focusable="false"><use href="#cx-icon-arrow-back"></use></svg>All writing</a>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Do
|
|
70
|
-
|
|
71
|
-
- Use `<a>` when it goes somewhere and `<button>` when it does something.
|
|
72
|
-
- Write labels as verb plus object, in sentence case.
|
|
73
|
-
- Keep `cx-button` pill-shaped (`radius.pill`). Pills are reserved for buttons, nav items and icon-only controls (the copy button, the theme toggle, the backdrop pause, heading anchors), so a pill always means "you can press this".
|
|
74
|
-
- Use the `arrow-forward` and `arrow-back` icons (see `icon.md`) with `cx-button__arrow`; they nudge by `motion.distance.nudge` on hover, in their own direction.
|
|
75
|
-
|
|
76
|
-
## Don't
|
|
77
|
-
|
|
78
|
-
- Don't use buttons for decoration or as tags.
|
|
79
|
-
- Don't round anything else: cards, tags, labels, tooltips and inputs stay square.
|
|
80
|
-
- Don't make disabled buttons look clickable. They are dashed and muted, and should say why they're unavailable.
|
|
81
|
-
- Don't add icons beyond the direction arrow.
|
|
82
|
-
|
|
83
|
-
## Accessibility
|
|
84
|
-
|
|
85
|
-
- Buttons are 40px tall (`size.target.control`); links at least 24px.
|
|
86
|
-
- Focus shows `color.focus.ring` 2px off the element, so it never sits on the green fill.
|
|
87
|
-
- Pairs: `color.text.on-accent` on `color.accent.fill.rest` and `.hover` (4.5:1); `color.accent.fill.rest` against the page (3:1); secondary border `color.border.strong` (3:1); `color.link.rest` (7:1).
|
|
1
|
+
---
|
|
2
|
+
name: button-and-link
|
|
3
|
+
status: stable
|
|
4
|
+
tokens:
|
|
5
|
+
- border.focus.offset
|
|
6
|
+
- border.focus.width
|
|
7
|
+
- border.width.emphasis
|
|
8
|
+
- border.width.hairline
|
|
9
|
+
- color.accent.fill.hover
|
|
10
|
+
- color.accent.fill.rest
|
|
11
|
+
- color.border.strong
|
|
12
|
+
- color.focus.ring
|
|
13
|
+
- color.link.hover
|
|
14
|
+
- color.link.rest
|
|
15
|
+
- color.surface.hover
|
|
16
|
+
- color.surface.raised
|
|
17
|
+
- color.text.muted
|
|
18
|
+
- color.text.on-accent
|
|
19
|
+
- color.text.primary
|
|
20
|
+
- font.family.body
|
|
21
|
+
- font.family.mono
|
|
22
|
+
- font.line-height.ui
|
|
23
|
+
- font.size.label
|
|
24
|
+
- font.size.small
|
|
25
|
+
- font.tracking.label
|
|
26
|
+
- font.weight.strong
|
|
27
|
+
- font.weight.ui
|
|
28
|
+
- motion.distance.nudge
|
|
29
|
+
- motion.duration.fast
|
|
30
|
+
- motion.easing.standard
|
|
31
|
+
- radius.pill
|
|
32
|
+
- size.target.control
|
|
33
|
+
- size.target.min
|
|
34
|
+
- space.inline.md
|
|
35
|
+
- space.inline.sm
|
|
36
|
+
- space.inline.xs
|
|
37
|
+
- space.inset.lg
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
# Button and link
|
|
41
|
+
|
|
42
|
+
Buttons start actions or journeys; standalone links and back links move between pages.
|
|
43
|
+
|
|
44
|
+
## When to use
|
|
45
|
+
|
|
46
|
+
- `cx-button--primary`: the one main action in a view ("View work").
|
|
47
|
+
- `cx-button`: a secondary action beside it.
|
|
48
|
+
- `cx-link`: a standalone forward link at the end of a section ("All projects" plus a forward arrow).
|
|
49
|
+
- `cx-back`: the return link at the top of a post or case study (back arrow plus "All writing").
|
|
50
|
+
|
|
51
|
+
## When not to use
|
|
52
|
+
|
|
53
|
+
- For inline links in text; `prose` styles those.
|
|
54
|
+
- Two primary buttons in one view. Make the second one secondary.
|
|
55
|
+
- For navigation between sibling posts; use `pagination`.
|
|
56
|
+
|
|
57
|
+
## Markup
|
|
58
|
+
|
|
59
|
+
```html preview
|
|
60
|
+
<div class="cx-actions">
|
|
61
|
+
<a class="cx-button cx-button--primary" href="/work/">View work <svg class="cx-icon cx-button__arrow" aria-hidden="true" focusable="false"><use href="#cx-icon-arrow-forward"></use></svg></a>
|
|
62
|
+
<a class="cx-button" href="/writing/">Read the writing</a>
|
|
63
|
+
<button class="cx-button" type="button" disabled>Not yet published</button>
|
|
64
|
+
</div>
|
|
65
|
+
<a class="cx-link" href="/work/">All projects <svg class="cx-icon cx-button__arrow" aria-hidden="true" focusable="false"><use href="#cx-icon-arrow-forward"></use></svg></a>
|
|
66
|
+
<a class="cx-back" href="/writing/"><svg class="cx-icon cx-icon--sm cx-button__arrow" aria-hidden="true" focusable="false"><use href="#cx-icon-arrow-back"></use></svg>All writing</a>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Do
|
|
70
|
+
|
|
71
|
+
- Use `<a>` when it goes somewhere and `<button>` when it does something.
|
|
72
|
+
- Write labels as verb plus object, in sentence case.
|
|
73
|
+
- Keep `cx-button` pill-shaped (`radius.pill`). Pills are reserved for buttons, nav items and icon-only controls (the copy button, the theme toggle, the backdrop pause, heading anchors), so a pill always means "you can press this".
|
|
74
|
+
- Use the `arrow-forward` and `arrow-back` icons (see `icon.md`) with `cx-button__arrow`; they nudge by `motion.distance.nudge` on hover, in their own direction.
|
|
75
|
+
|
|
76
|
+
## Don't
|
|
77
|
+
|
|
78
|
+
- Don't use buttons for decoration or as tags.
|
|
79
|
+
- Don't round anything else: cards, tags, labels, tooltips and inputs stay square.
|
|
80
|
+
- Don't make disabled buttons look clickable. They are dashed and muted, and should say why they're unavailable.
|
|
81
|
+
- Don't add icons beyond the direction arrow.
|
|
82
|
+
|
|
83
|
+
## Accessibility
|
|
84
|
+
|
|
85
|
+
- Buttons are 40px tall (`size.target.control`); links at least 24px.
|
|
86
|
+
- Focus shows `color.focus.ring` 2px off the element, so it never sits on the green fill.
|
|
87
|
+
- Pairs: `color.text.on-accent` on `color.accent.fill.rest` and `.hover` (4.5:1); `color.accent.fill.rest` against the page (3:1); secondary border `color.border.strong` (3:1); `color.link.rest` (7:1).
|