5 · A design system with tokens

Lesson 5 of 8 — move colours, spacing and radii into the config and reference them with `$group.key`.

1 min readv1

Hard-coded values drift: one screen uses #4F52D9, another #4f47e6. Tokens give every value a name and a single definition.

You will learn: defining tokens · referencing them · tokens inside larger values · naming conventions.

Define tokens#

TypeScript
// nibcss.config.ts
import { defineConfig } from "@nibcss/core";

export default defineConfig({
  tokens: {
    color: {
      brand: "#4F52D9",
      "brand-hover": "#3A3DBF",
      ink: "#0f172a",
      muted: "#64748b",
      surface: "#ffffff",
      border: "#e2e8f0",
    },
    space: { xs: "4px", sm: "8px", md: "16px", lg: "24px", xl: "40px" },
    radius: { sm: "6px", md: "10px", lg: "16px", pill: "999px" },
    font: { sans: "Inter, system-ui, sans-serif", mono: "ui-monospace, monospace" },
  },
});

Tokens are grouped (color, space, …); group and key names are yours to choose.

Use them#

Reference a token as $group.key — or $group-key, both work:

HTML
<button nib="bgc=$color.brand; cl=#fff; p=$space.sm $space.md; bdrd=$radius.md; hover:bgc=$color.brand-hover">
  Save
</button>

Tokens work anywhere in a value, not just as the whole value:

HTML
<div nib="bd=1px solid $color.border; bxsh=0 0 0 4px $color.brand; p=$space.md $space.lg">

Typos are caught#

A token that does not exist is reported with a suggestion:

Text
Unknown token "$color.brnd" — did you mean "color.brand"?

Naming that scales#

  • Name by role, not by value: brand, danger, surface — not indigo or red-500. Then a rebrand is a one-line change.
  • Keep scales short: five spacing steps cover almost every layout.
  • Pair states: brand / brand-hover, surface / surface-dark.

Next steps#