diff options
Diffstat (limited to 'docs/typ/style.typ')
| -rw-r--r-- | docs/typ/style.typ | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/docs/typ/style.typ b/docs/typ/style.typ index cf55ae86..903a8273 100644 --- a/docs/typ/style.typ +++ b/docs/typ/style.typ @@ -56,9 +56,12 @@ (id: "scripting", title: "Scripting", file: "scripting.typ"), (id: "reference", title: "Reference", file: "reference.typ"), (id: "themes", title: "Themes", file: "themes.typ"), - (id: "building", title: "Building", file: "building.typ"), + (id: "building", title: "Building, for contributors", file: "building.typ"), ) +/// The one-line pitch: the A4 sheet's header and the site's landing page. +#let tagline = "acme's tags and three buttons, helix's keys, terminals as panes, the editor as a 9P filesystem" + /// The tutor, shown as it is in the editor (`Tutor`), from the repo root. #let tutor-path = "/src/tutor.txt" @@ -75,7 +78,9 @@ /// pill: a combination's parts joined by a muted +, a sequence's steps by a /// muted › (`Ctrl-w h` reads Ctrl + w › h). #let key(k) = context if html-out() { - html.elem("kbd", k.split(" ").map(t => html.elem("kbd", t)).join(" ")) + let sep(c, cls) = html.elem("span", attrs: (class: cls, "aria-hidden": "true"), c) + let press(t) = (if t.len() > 1 and t.contains("-") { t.split("-") } else { (t,) }).join(sep("+", "plus")) + html.elem("kbd", attrs: (class: "key"), k.split(" ").map(press).join(sep("›", "then"))) } else { let muted(c) = text(fill: palette.grip.transparentize(25%), size: 0.85em, c) let press(t) = (if t.len() > 1 and t.contains("-") { t.split("-") } else { (t,) }).join(muted[+]) @@ -91,6 +96,9 @@ #let keys(..ks) = context ks.pos().map(key).join(if html-out() [ ] else { h(0.25em) }) #let button-names = ("B1": "left button", "B2": "wheel", "B3": "right button") +#let click-names = ("B1": "left", "B2": "middle", "B3": "right") +/// Text that is read and copied but not shown, beside a drawn glyph. +#let hidden(t) = html.elem("span", attrs: (class: "vh"), t) /// A mouse, about cap height: left button, wheel, right button. The parts /// in `pressed` ("B1", "B2", "B3") are filled. @@ -116,10 +124,33 @@ }) } +/// The same mouse as inline SVG for HTML. Each part is classed `on` +/// (pressed) or `off`, and the stylesheet colours them: the pressed part +/// filled in the accent, the rest outlined and muted. +#let mouse-svg(pressed) = { + let cls(b) = if b in pressed { "on" } else { "off" } + let part(d, b) = html.elem("path", attrs: (class: cls(b), d: d)) + html.elem("svg", attrs: (class: "mouse", viewBox: "-6 -6 96 132", "aria-hidden": "true"), { + // taller buttons and a slimmer wheel than on paper, so a pressed + // button shows as a solid block at body size + part("M0 64H84V78A42 42 0 0 1 0 78Z", none) + part("M0 64V42A42 42 0 0 1 42 0V64Z", "B1") + part("M42 0A42 42 0 0 1 84 42V64H42Z", "B3") + // a pressed wheel is drawn wider, so it reads as pressed, not as a seam + let (hx, hw, wx, ww) = if "B2" in pressed { ("27", "30", "31", "22") } else { ("31", "22", "35", "14") } + html.elem("rect", attrs: (class: "halo", x: hx, y: "4", width: hw, height: "48", rx: "13")) + html.elem("rect", attrs: (class: "wheel " + cls("B2"), x: wx, y: "8", width: ww, height: "40", rx: "9")) + }) +} + /// A mouse button; `shift: true` for the button with Shift held. #let btn(b, shift: false) = context if html-out() { let label = (if shift { "shift " } else { "" }) + button-names.at(b) - html.elem("span", attrs: (class: "btn", aria-label: label, title: label), (if shift { "⇧" } else { "" }) + b) + html.elem("span", attrs: (class: "btn", title: label), { + if shift { html.elem("span", attrs: (class: "shift", "aria-hidden": "true"), "⇧") } + mouse-svg((b,)) + hidden((if shift { "Shift-" } else { "" }) + click-names.at(b) + "-click") + }) } else { if shift { text(size: 0.8em, fill: palette.col-grip)[⇧] } mouse((b,)) @@ -130,7 +161,13 @@ /// down, with arrows between. #let chord(..bs) = context if html-out() { let label = bs.pos().map(b => button-names.at(b)).join(" then ") - html.elem("span", attrs: (class: "chord", aria-label: label, title: label), bs.pos().join("-")) + let (held, ..clicks) = bs.pos() + let arrow = html.elem("span", attrs: (class: "then", "aria-hidden": "true"), "›") + let said = "hold " + click-names.at(held) + ", click " + clicks.map(c => click-names.at(c)).join(", then ") + html.elem("span", attrs: (class: "chord", title: label), { + ((mouse-svg((held,)),) + clicks.map(c => mouse-svg((held, c)))).join(arrow) + hidden(said) + }) } else { let (held, ..clicks) = bs.pos() let arrow = text(size: 0.75em, fill: palette.col-grip)[#h(0.5pt)›#h(0.5pt)] @@ -145,6 +182,7 @@ /// A whole tagline: its grip, the path, then its words. #let tag(words, path: none) = context if html-out() { html.elem("div", attrs: (class: "tag"), { + html.elem("span", attrs: (class: "grip", "aria-hidden": "true"))[] if path != none { span("path", path); [ ] } raw(words) }) @@ -215,3 +253,20 @@ } } } + +/// Where pardes lives and under what licence, for the site's footer (and +/// any output that wants them). none until decided. +#let project = (source: none, license: none) + +/// A glossary: like #pairs, under its own heading. On paper the heading +/// and the table; in HTML a <details> that starts closed, its summary the +/// heading and the count, so a reader who knows the words skips them. +#let glossary(title, lbl, ..cells) = context if html-out() { + html.elem("details", attrs: (class: "glossary"), { + html.elem("summary", [#heading(title) #lbl #html.elem("span", attrs: (class: "count"), "(" + str(calc.quo(cells.pos().len(), 2)) + ")")]) + pairs(..cells) + }) +} else { + [#heading(title) #lbl] + pairs(..cells) +} |
