Blueprint

blueprint is a technical drawing: hairlines on a near-black sheet, square corners, and a registration mark — a small cross — on each corner of a card, a dialog and a row of stats. Everything that names or operates something — a button, a field’s label, a tab, a tag, a column head, a link in the bar — is set in a monospace face, in widely spaced capitals, while headings and running text stay in a grotesk, set tight. A solid line is an edge and a dashed one divides what is inside it, as a drawing marks a hidden line: the rows of a table, a divider, the run to a step still to come. It keeps to few colours. The solid button, a checked box, a filled bar and anything chosen are ink, printed in reverse; one blueprint blue marks focus and the tag over a heading; success, warning and danger keep theirs for what they say. Nothing casts a shadow. Dark mode is the original look; light mode keeps every line and mark and prints it in ink on white paper.

A card

The same markup, restyled by one sheet.

  1. Account

  2. Profile

  3. Confirm

Progress50%
50
Saved
Your changes are live.
Copied to clipboard
What is a preset?
A second sheet that restyles every component at once.
Does it follow dark mode?
Yes — try the toggle at the top of the page.
Can I still use theme()?
Yes, and it wins over the preset.
  1. Today

    Preset shipped

    The whole look, in one call.

  2. Yesterday

    Docs written

  3. Monday

    First sketch

The whole look, in one call.
Link it after the core sheet.
One option: preset.
DraftLiveArchived
AL312GH

Using it

import { iconSet, styles } from 'sitelo/ui'

iconSet('square')

head(
  title('My site'),
  styles({ preset: 'blueprint' }),
)
// <link rel="stylesheet" href="/su/ui-c9428b65.css">
// <link rel="stylesheet" href="/su/blueprint-4d1f8a20.css">

iconSet('square') draws the icons to match — straight hairlines with square ends and sharp corners, as in the preview above — the ones components draw for themselves included. Call it once, from a module your pages import.

Paint the page with var(--su-bp-backdrop) for the preset’s ground with a faint grid ruled across it, or with plain var(--su-bg). The preset uses Geist or Inter, and Geist Mono, JetBrains Mono or IBM Plex Mono, when the page loads them, and the system’s own faces otherwise; it downloads nothing.

body {
  background: var(--su-bp-backdrop);
  color: var(--su-text);
  font-family: var(--su-font-sans);
}

Your own colours

theme() still works on top, so a preset is a starting point rather than a fork. The primary palette is the ink — the solid button, a checked box, a filled bar, whatever is chosen — so primary recolours all of it at once. The rest are the preset’s own: --su-bp-accent, the blue that draws focus and keys a heading; --su-bp-mark, the registration marks, which transparent takes away; --su-bp-field, the line round a field; --su-bp-track, the slot a progress bar runs in; --su-bp-grid and --su-bp-cell, the backdrop’s lines and the size of its squares; and --su-bp-tracking, how far apart a label’s capitals are set. Here the blue turns to a signal orange, and the marks with it.

head(
  styles({ preset: 'blueprint' }),
  theme(
    { bpAccent: '#c2410c', bpMark: '#c2410c' },
    { dark: { bpAccent: '#ff7a3d', bpMark: '#ff7a3d' } },
  ),
)