summaryrefslogtreecommitdiff
path: root/docs/typ/style.typ
blob: 7cb05e23de0046245fcea6475ec5b8acd97cd9d6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// The semantic elements every docs/typ topic uses, and the one place they
// are defined. Content files call them ("this is a key", "this is a
// builtin"); how each looks is decided here, per output: paged outputs
// (the A4 cheatsheet, later the book) draw them, HTML export gives them
// elements and classes for a stylesheet. Page geometry and fonts belong to
// the output wrappers beside this file.

/// The `atelier` theme (src/themes/atelier.zig): pardes's acme homage,
/// butter paper and blue-green tags.
#let palette = (
  paper: rgb("#fffdeb"),
  ink: rgb("#293f35"),
  tag-bg: rgb("#e4f0ed"),
  tag-fg: rgb("#3d6055"),
  tag-name: rgb("#6e4774"),
  grip: rgb("#36826b"),
  col-grip: rgb("#955815"),
  str: rgb("#34743d"),
  num: rgb("#9a5810"),
  rule: rgb("#95baa2"),
)
#let mono = "DejaVu Sans Mono"

/// Topic ids for #doc. Each names the document that holds the topic today;
/// as topics move into docs/typ the value becomes the HTML page or chapter.
#let topics = (
  tags: "docs/tags.md",
  fs: "docs/fs.md",
  config: "docs/config.md",
  themes: "docs/themes.md",
  keys: "docs/helix-keys.md",
  detached: "docs/detached.md",
)

#let html-out() = target() == "html"
#let span(class, body) = html.elem("span", attrs: (class: class), body)
#let m(s, fill: palette.ink) = text(font: mono, size: 0.92em, fill: fill, s)

/// A key or a sequence of keys, one cap per space-separated chord.
#let key(k) = context if html-out() {
  k.split(" ").map(t => html.elem("kbd", t)).join(" ")
} else {
  k.split(" ").map(t => box(
    fill: white, stroke: 0.4pt + palette.rule, radius: 1.5pt,
    inset: (x: 1.6pt, y: 0pt), outset: (y: 1.4pt), m(t),
  )).join(h(1pt))
}

/// A mouse button.
#let btn(b) = context if html-out() { span("btn", b) } else {
  box(
    fill: palette.col-grip, radius: 2pt, inset: (x: 1.6pt, y: 0pt), outset: (y: 1.4pt),
    text(font: mono, size: 0.85em, weight: "bold", fill: white, b),
  )
}

/// A chord: the first button held, the others clicked.
#let chord(..bs) = bs.pos().map(btn).join(text(fill: palette.col-grip)[--])

/// A tag word or builtin, as it sits in a tag.
#let word(w) = context if html-out() { span("word", raw(w)) } else {
  box(fill: palette.tag-bg, inset: (x: 1.4pt, y: 0pt), outset: (y: 1.4pt), m(w, fill: palette.tag-fg))
}

/// 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"), {
    if path != none { span("path", path); [ ] }
    raw(words)
  })
} else {
  block(width: 100%, fill: palette.tag-bg, inset: (x: 2pt, y: 2.4pt), spacing: 0.5em, {
    box(fill: palette.grip, width: 0.55em, height: 0.75em, baseline: 0.1em)
    h(3pt)
    if path != none { m(path, fill: palette.tag-name); h(0.6em) }
    m(words, fill: palette.tag-fg)
  })
}

/// A look address.
#let addr(a) = context if html-out() { span("addr", raw(a)) } else { m(a, fill: palette.tag-name) }

/// A 9P path.
#let file(p) = context if html-out() { span("file", raw(p)) } else { m(p, fill: palette.str) }

/// A shell line.
#let cmd(c) = context if html-out() { raw(c, block: true, lang: "sh") } else {
  block(
    width: 100%, inset: (left: 3pt, y: 1.2pt), spacing: 0.4em,
    stroke: (left: 1pt + palette.rule),
    text(font: mono, size: 0.85em, fill: palette.ink, c),
  )
}

/// Where the full story is: a topic id from `topics`, and a section in it.
#let doc(id, section: none) = {
  let to = topics.at(id) + if section != none { "#" + section } else { "" }
  context if html-out() { link(to)[→ #to] } else {
    text(fill: palette.num)[→#m(to, fill: palette.num)]
  }
}