Lyse UI
v1.1

Design Tokens

A 3-layer token system built on CSS custom properties. Colors, typography, spacing, and layout — with automatic light/dark mode support.

Architecture

Each layer adds meaning. Primitives hold raw values, semantics assign purpose, and the bridge maps to shadcn/Tailwind utilities.

text
Primitives (root-*.css)
  --root-color-brand-500, --root-space-4, --root-font-size-md
         ↓
Semantics (semantic-*.css)
  --background-brand-strong-default, --text-base-strong
         ↓
Bridge (shadcn-bridge.css)
  --primary, --foreground, --ring

Primitives

Raw values with no semantic meaning. Five color scales (brand, danger, neutral, success, warning) with 50–950 steps, plus typography and layout values.

root-colors.css — Color palette (oklch)root-typography.css — Font sizes, weights, line heightsroot-layout.css — Spacing, radius, borders, sizing
root-*.css
--root-color-brand-500: oklch(61.87% 0.2067 259.23);
--root-color-neutral-950: oklch(16.84% 0.0000 none);
--root-font-size-md: 1rem;
--root-space-4: 0.5rem;
--root-radius-4: 0.5rem;

Semantics

Named by purpose, not value. Semantic tokens reference primitives and remap automatically between light and dark mode. Components consume these in their .css files.

semantic-colors.css — Background, text, border, icon tokenssemantic-global.css — Mode-independent layout aliasestypography.css — Composite classes (.text-content-body, .text-heading-small)
semantic-colors.css
/* Light (:root) */
--background-base: var(--root-color-neutral-050);
--text-base-strong: var(--root-color-neutral-950);
--border-default: var(--root-opacity-neutral-300);

/* Dark (.dark) */
--background-base: var(--root-color-neutral-950);
--text-base-strong: var(--root-color-neutral-050);
--border-default: var(--root-opacity-inverse-300);

Bridge

Maps Lyse semantic tokens to shadcn variable names. This makes components compatible with the shadcn ecosystem and Tailwind utilities like bg-primary or text-foreground.

shadcn-bridge.css
--background: var(--background-base);
--foreground: var(--text-base-strong);
--primary: var(--background-brand-strong-default);
--destructive: var(--background-danger-strong-default);
--ring: var(--border-selected);

Usage in components

Component CSS files use Layer 2 tokens for theming (colors, borders, shadows). Layout properties use dedicated layout tokens.

button.css
/* button.css — theming via Layer 2 tokens */
.button-primary {
  background: var(--background-brand-strong-default);
  color: var(--text-inverse);
}
.button-primary:hover {
  background: var(--background-brand-strong-hover);
}
layout tokens
/* Structure via layout tokens */
padding: var(--layout-padding-md);
gap: var(--layout-gap-sm);
border-radius: var(--layout-radius-lg);

Dark mode

Add the dark class to any ancestor. Semantic tokens remap automatically — no component changes needed.

semantic-colors.css
:root {
  --text-base-strong: var(--root-color-neutral-950);
}
.dark {
  --text-base-strong: var(--root-color-neutral-050);
}