Skip to content

August 16, 2026 · 3 min read

"Semantic tokens: why you theme meanings, not components"

"Theme Kit themes semantic tokens — background, foreground, primary, muted — instead of component classes. Here's why that scales to every framework and every component library."

tokensdesign-systemsconcepts

Component-based theming asks "what color is a button?" and then writes .button { background: #6366f1 }. That works until you have three button variants, a dark mode, and a second component library to theme. Semantic tokens flip the question: theme meanings, and let every component resolve its own look from them.

Tokens, not hex values

Instead of hard-coding colors into components, you define a small set of semantic meanings:

ts
1import { defineTheme } from "@theme-kit/core";
2
3export const lightTheme = defineTheme({
4  name: "app-light",
5  meta: { family: "app", mode: "light" },
6  tokens: {
7    colors: {
8      background: "#fafafa",
9      foreground: "#18181b",
10      card: "#ffffff",
11      primary: "#6366f1",
12      primaryForeground: "#ffffff",
13      muted: "#f4f4f5",
14      mutedForeground: "#71717a",
15      destructive: "#ef4444",
16      destructiveForeground: "#ffffff",
17      success: "#16a34a",
18      successForeground: "#ffffff",
19      border: "#e4e4e7",
20      ring: "#6366f1",
21    },
22    radius: { lg: "12px" },
23  },
24});

Components consume the meaning — primary, muted, border — never a literal color. When the theme changes, every consumer updates together.

The cascade: tokens → CSS variables → components

At runtime Theme Kit flattens tokens into CSS custom properties:

text
--theme-color-background: #fafafa;
--theme-color-primary: #6366f1;
--theme-color-mutedForeground: #71717a;
--theme-radius-lg: 12px;

Your components reference the variables (or the framework hook), so the whole tree re-themes in one DOM update:

tsx
1import { useThemeTokens } from "@theme-kit/react";
2
3function Card() {
4  const tokens = useThemeTokens();
5  return (
6    <div
7      style={{
8        background: tokens.colors?.card,
9        borderColor: tokens.colors?.border,
10      }}
11    >
12      {children}
13    </div>
14  );
15}

Why meanings scale

  • One theme, many surfacesprimary means "the main action color" everywhere: buttons, links, focus rings, active states.
  • Dark mode for free — swap the token set, not the components. A component written against tokens renders correctly in both modes with zero changes.
  • Framework-agnostic — the same tokens feed React, Vue, Svelte, Angular, Web Components, and CSS-only Tailwind projects. The runtime is the shared contract.
  • Component-library adapters — Theme Kit can map tokens into MUI, Chakra, Ant Design, shadcn/ui, Bootstrap, and more, because those libraries already accept token-ish inputs.

Extending tokens safely

Tokens are plain objects, so they compose:

ts
1import { extendTheme } from "@theme-kit/core";
2
3// Add a brand family without touching the base
4export const brandLight = extendTheme("app-light", {
5  meta: { family: "brand", mode: "light" },
6  colors: {
7    primary: "#0ea5e9",   // override just what you need
8  },
9});

extendTheme merges deeply — nested colors, radius, shadows, and the code block all inherit unless overridden. You can layer a family, a mode, or a brand on top of a base theme.

Semantic tokens and accessibility

Because contrast pairs are semantic (foreground on background, primary on primaryForeground), Theme Kit can audit them:

ts
import { validateThemeContrast } from "@theme-kit/core";

const result = validateThemeContrast(theme, { themes });
// { valid, checks: [{ foregroundToken, backgroundToken, ratio, passesAALarge, … }] }

A component that consumes foreground on background is automatically checked — no manual mapping from "component X uses color Y" required.

The whole docs site you're reading runs on this: every card, button, and code block reads from the live theme's tokens. That's the semantic-token payoff — theming that stays honest at scale.

"Semantic tokens: why you theme meanings, not components" — Theme Kit