Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ task check # what CI runs: fails on a pair below its floor, or a stale dist
Type and layout are tokens too: IBM Plex Sans and Mono (`fonts/`, OFL), a 16 px reading size
(below it iOS zooms into a focused input) and 14 px for the dashboard's tables, a 72ch measure,
24 px for any pointer target and 44 px on a coarse pointer (WCAG 2.2, 2.5.8 and 2.5.5).
Motion is four durations and one easing (`--spin-duration-*`, `--spin-ease`): a movement says
what something does or that it answered a hand, runs once, and is its end state under reduced
motion.

## Where it goes

Expand Down
4 changes: 4 additions & 0 deletions cmd/palette/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ type palette struct {
TargetTouch int `toml:"target_touch"`
Phone, Tablet, Desktop int
}
Motion struct {
Fast, Base, Slow, Draw int
Ease string
}
}

func main() {
Expand Down
13 changes: 9 additions & 4 deletions cmd/palette/outputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func outputs(p palette, results []result) (map[string][]byte, error) {

j, err := json.MarshalIndent(map[string]any{
"brand": p.Brand, "dark": hexes(dark), "light": hexes(light),
"tint": p.Tint, "type": p.Type, "layout": p.Layout,
"tint": p.Tint, "type": p.Type, "layout": p.Layout, "motion": p.Motion,
}, "", " ")
if err != nil {
return nil, err
Expand Down Expand Up @@ -55,8 +55,8 @@ func sortedKeys(m map[string]rgb) []string {
return keys
}

// tokensCSS is every role as --spin-<role>: dark on :root, light under data-theme="light", and
// the type and layout tokens beside them.
// tokensCSS is every role as --spin-<role>: dark on :root and .spin-dark, light under
// data-theme="light", and the type, layout and motion tokens beside them.
func tokensCSS(p palette, dark, light map[string]rgb) string {
var b strings.Builder
b.WriteString(header)
Expand All @@ -69,7 +69,9 @@ func tokensCSS(p palette, dark, light map[string]rgb) string {
fmt.Fprintf(&b, "\t--spin-accent-selected: %s;\n", c["accent"].over(c["page"], p.Tint.Selected).hex())
b.WriteString("}\n")
}
block(":root", dark)
// .spin-dark is a part that is dark in either theme - a terminal, a drawing on the navy - and
// takes the dark roles in place of the page's.
block(":root, .spin-dark", dark)
block(":root[data-theme='light']", light)
b.WriteString(":root {\n")
names := make([]string, 0, len(p.Brand))
Expand All @@ -88,6 +90,9 @@ func tokensCSS(p palette, dark, light map[string]rgb) string {
fmt.Fprintf(&b, "\t--spin-measure: %dch;\n\t--spin-sidebar: %drem;\n", p.Layout.Measure, p.Layout.Sidebar)
fmt.Fprintf(&b, "\t--spin-radius-sm: %dpx;\n\t--spin-radius: %dpx;\n\t--spin-radius-lg: %dpx;\n", p.Layout.RadiusSm, p.Layout.Radius, p.Layout.RadiusLg)
fmt.Fprintf(&b, "\t--spin-target: %dpx;\n\t--spin-target-touch: %dpx;\n", p.Layout.Target, p.Layout.TargetTouch)
fmt.Fprintf(&b, "\t--spin-duration-fast: %dms;\n\t--spin-duration: %dms;\n", p.Motion.Fast, p.Motion.Base)
fmt.Fprintf(&b, "\t--spin-duration-slow: %dms;\n\t--spin-duration-draw: %dms;\n", p.Motion.Slow, p.Motion.Draw)
fmt.Fprintf(&b, "\t--spin-ease: %s;\n", p.Motion.Ease)
b.WriteString("}\n")
return b.String()
}
Expand Down
7 changes: 6 additions & 1 deletion dist/tokens.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Written by `task palette` from palette.toml (spin-stack/brand). Edit palette.toml, not this file. */
:root {
:root, .spin-dark {
--spin-accent: #27BFE8;
--spin-accent-text: #27BFE8;
--spin-border: #33435F;
Expand Down Expand Up @@ -60,4 +60,9 @@
--spin-radius-lg: 12px;
--spin-target: 24px;
--spin-target-touch: 44px;
--spin-duration-fast: 120ms;
--spin-duration: 200ms;
--spin-duration-slow: 400ms;
--spin-duration-draw: 700ms;
--spin-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}
7 changes: 7 additions & 0 deletions dist/tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@
"text": "#111827",
"warning": "#8A5A00"
},
"motion": {
"Fast": 120,
"Base": 200,
"Slow": 400,
"Draw": 700,
"Ease": "cubic-bezier(0.2, 0.7, 0.2, 1)"
},
"tint": {
"Hover": 0.1,
"Selected": 0.22
Expand Down
11 changes: 11 additions & 0 deletions palette.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,14 @@ target_touch = 44 # px: a target on a coarse pointer (WCAG 2.5.5, Apple's
phone = 390 # px: the narrow width every page is drawn at in preview.html
tablet = 768
desktop = 1280

# Motion. A movement says what something does - a layer sealed on the one under it, a diff drawn
# between two - or that it answered a hand; one that only decorates is left out. Each runs once:
# nothing moves on its own for longer than 5 s (WCAG 2.2.2), and reduced motion asked for is
# every one at its end state.
[motion]
fast = 120 # ms: a hover, a press, a focus ring
base = 200 # ms: a card, a tab, a menu opening
slow = 400 # ms: a section coming into view
draw = 700 # ms: a line of a drawing being drawn
ease = "cubic-bezier(0.2, 0.7, 0.2, 1)" # out, quick then settling: it arrives rather than bounces
Loading