Skip navigation

UI kit

A single page holding every element the rest of the site is built from. I keep it around mostly to catch regressions: after a change to the design tokens or a shared component, this page is the fastest way to see what moved.

Headings

Headings

Headings

Headings

Text

Body copy is set in Geist at a line height of 1.7 and capped near 68 characters, which is roughly the width at which the eye can find the start of the next line without hunting for it. Headings use Neue Machina with negative tracking, so they close up as they get larger instead of drifting apart.

The two faces do different jobs. Neue Machina has too much personality to read four paragraphs of, and Geist has too little to carry a title. Pairing them means neither has to do the other’s work.

internal link
external link

Lists

  • Item one
  • Item two
    • Item three
  • Item four with link
  1. Item one
  2. Item two
  3. Item three
  4. Item four with link

Code

function bubbleSort(data: number[]) {
  for (let i: number = 0; i < data.length; i++) {
    for (let j: number = 0; j < data.length; j++) {
      if (data[i] > data[j]) {
        const tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
      }
    }
  }

  return data;
}

This is an example of inline code.

Picture

Man standing on a mountain peak with expansive views of the surrounding landscape below
Captions sit centred under the frame, one step down in size

Alerts

Four states, each with its own glyph so the meaning survives without colour. The surface is a quiet tint and the state colour is carried by the left edge, which keeps body text on the page ink at full contrast.