Contents

Theme colours

Editors change the theme at runtime in Site settings → Theme (see Theme and design tokens). The defaults, and how the theme becomes CSS, live in code.

Change the defaults #

  1. Edit DEFAULT_THEME in src/theme/tokens.ts: the seven base colours and the two tints, as hex values.

    export const DEFAULT_THEME: Theme = {
      colors: {
        brand: '#2f54c8',
        ink: '#0f1115',
        highlight: '#6f97f2',
        signal: '#d9603f',
        surface: '#d6d3ce',
        success: '#4f9d69',
        error: '#cf5d5d',
      },
      tints: { 'tint-20': '#f9fafb', 'tint-50': '#f1f3f6' },
    }
  2. Regenerate the CSS:

    pnpm generate:theme

    This rewrites src/theme/theme.css: every variable, and the list of classes built at runtime. Commit it; a test fails when it is not exactly what the generator makes.

  3. Run pnpm test:unit. The contrast tests check that text on every background reaches 4.5:1.

The defaults reach every site, running ones included, on its next deploy. Site settings store only the colours an admin set in Site settings → Theme: those win, and every colour left empty follows DEFAULT_THEME. The Theme fields show the default in grey while they are empty.

A site whose settings were saved before the kit worked this way stored every colour, so it keeps its old ones. To let a colour follow the defaults again, press Use default beside it in Site settings → Theme, or empty the field, and save.

How a colour becomes a scale #

generateScale() mixes the base colour with white for the light steps and with black for the dark ones: 50 is 5 % colour, 400 is 50 %, 500 is the colour itself, and 900 is 20 % colour with black. Every step becomes a variable (--color-brand-500) and a utility (bg-brand-500, text-brand-500/60).

Readable text #

For every background token the theme also writes:

  • text-on-<token>: black or white, whichever has more contrast.
  • text-on-<token>-accent: the eyebrow and link colour, a brand step where it reaches 4.5:1 on that background, else black or white.

Use them through getSurface(token) (src/components/sections/surface.ts) and getPanelRecipe(token). Never put text-brand-500 on a background you do not control: a light brand colour, a yellow say, would be unreadable on white.

Rules the code keeps #

  • Semantic names only. Colours are brand, ink, signal and so on, never a company's colour names. A test checks.
  • Editors store tokens, such as brand-500, never hex values, so a theme change reaches every block.
  • No capitals by CSS. Eyebrows get their feel from small type and letter-spacing, never text-transform.

These guides ship with Tolk Starter 0.6.0: buyers get the same pages in their repository, next to the code they describe.