Semantic Tokens & Typography
@theme-kit/core — the token system
Theme Kit isn't another dark-mode library. Every theme is a complete design system — colors, typography, spacing, radius, shadows, border widths, z-index and breakpoints — flattened into semantic CSS variables that swap in one atomic update.
1Define every group in one theme
1import { defineTheme } from "@theme-kit/core";
2
3const brand = defineTheme({
4 name: "brand-light",
5 tokens: {
6 colors: {
7 primary: "#6d28d9",
8 secondary: "#ede9fe",
9 mutedForeground: "#6b7280",
10 },
11 typography: {
12 fontFamilies: { sans: "Inter, system-ui, sans-serif" },
13 fontSizes: { base: "1rem", "4xl": "2.25rem" },
14 lineHeights: { normal: "1.5" },
15 },
16 spacing: { "1": "4px", "4": "16px", "8": "32px" },
17 radius: { md: "8px", xl: "16px", full: "9999px" },
18 shadows: { md: "0 4px 6px rgba(0,0,0,0.07)" },
19 borderWidths: { "1": "1px", "2": "2px" },
20 zIndex: { dropdown: "1000", modal: "1100" },
21 breakpoints: { md: "768px" },
22 },
23});
24
25// themeToCSSVariables(brand) emits --theme-color-primary,
26// --theme-typography-font-size-4xl, --theme-spacing-4,
27// --theme-radius-full, --theme-border-width-2 and more.Adapters and build-time integrations consume the same resolved tokens — @theme-kit/tailwind maps them to --color-*, --radius-*, --spacing-*, --font-* and --shadow-* utilities.
Every theme validates against the full semantic color set — the base surfaces ( background, foreground, card, popover), interaction colors ( primary, secondary, accent, muted), and the status colors ( destructive, success) — each with its own *Foreground counterpart, plus border, input and ring. Missing any of them fails validateTheme.
2Token references & derived values
1import { defineTheme, resolveTokens } from "@theme-kit/core";
2
3const brand = defineTheme({
4 name: "brand",
5 tokens: {
6 colors: {
7 primary: "#6d28d9",
8 // Reference using $ prefix
9 primaryHover: "$colors.primary",
10 // Or using { } braces
11 ring: "{colors.primary}",
12 // Nested references work too
13 surface: {
14 primary: "$colors.primary",
15 hover: "{colors.primaryHover}",
16 },
17 },
18 spacing: {
19 "4": "16px",
20 // Expressions with calc()
21 "8": "calc($spacing.4 * 2)",
22 },
23 },
24});
25
26// Resolve all references to concrete values
27const resolved = resolveTokens(brand.tokens);
28// resolved.colors.primaryHover === "#6d28d9"
29// resolved.spacing["8"] === "32px"1import { defineTheme, resolveTokens } from "@theme-kit/core";
2
3const brand = defineTheme({
4 name: "brand",
5 tokens: {
6 colors: {
7 primary: "#6d28d9",
8 // Returns black or white based on WCAG luminance
9 primaryForeground: "contrast(#6d28d9)",
10 // Auto-derives readable foreground from base token
11 secondary: "#ede9fe",
12 secondaryForeground: "auto()",
13 // Works with references too
14 accent: "$colors.primary",
15 accentForeground: "auto($colors.primary)",
16 },
17 },
18});
19
20const resolved = resolveTokens(brand.tokens);
21// resolved.colors.primaryForeground === "#ffffff" (white on purple)
22// resolved.colors.secondaryForeground === "#1e1b4b" (dark on light purple)1import {
2 defineTheme,
3 extendTheme,
4 composeTheme,
5 mergeTokens,
6} from "@theme-kit/core";
7
8// Base theme with common tokens
9const base = defineTheme({
10 name: "base",
11 tokens: {
12 colors: {
13 background: "#ffffff",
14 foreground: "#0f172a",
15 primary: "#6366f1",
16 },
17 radius: { md: "8px", lg: "12px" },
18 spacing: { "4": "16px", "8": "32px" },
19 },
20});
21
22// Extend: create a variant with overrides
23const brandLight = extendTheme("brand-light", base, {
24 meta: { family: "brand", mode: "light" },
25 tokens: {
26 colors: {
27 primary: "#6d28d9",
28 accent: "#f5f3ff",
29 },
30 radius: { lg: "16px" },
31 },
32});
33
34// Compose: merge multiple themes into one
35const combined = composeTheme("combined", base, brandLight, {
36 tokens: { shadows: { md: "0 4px 6px rgba(0,0,0,0.1)" } },
37});
38
39// Low-level: merge token maps directly
40const customTokens = mergeTokens(brandLight.tokens, {
41 colors: { destructive: "#ef4444", success: "#16a34a" },
42 code: { background: "#f8f8f8" },
43});3Token helpers — complete examples
1import { flattenTokens } from "@theme-kit/core";
2
3const tokens = {
4 colors: { primary: "#6366f1", surface: { hover: "#ede9fe" } },
5 spacing: { "4": "16px" },
6};
7
8const flat = flattenTokens(tokens);
9// {
10// "colors.primary": "#6366f1",
11// "colors.surface.hover": "#ede9fe",
12// "spacing.4": "16px",
13// }1import { resolveTokens } from "@theme-kit/core";
2
3const tokens = {
4 colors: {
5 primary: "#6366f1",
6 ring: "$colors.primary",
7 surface: { primary: "{colors.primary}" },
8 },
9};
10
11const resolved = resolveTokens(tokens);
12// {
13// colors: {
14// primary: "#6366f1",
15// ring: "#6366f1",
16// surface: { primary: "#6366f1" },
17// },
18// }1import { themeToCSSVariables } from "@theme-kit/core";
2
3const vars = themeToCSSVariables(brand);
4// {
5// "--theme-color-primary": "#6d28d9",
6// "--theme-color-secondary": "#ede9fe",
7// "--theme-typography-font-family-sans": "Inter, system-ui, sans-serif",
8// "--theme-spacing-4": "16px",
9// "--theme-radius-lg": "12px",
10// "--theme-code-background": "#161b22",
11// "--theme-code-keyword": "#ff7b72",
12// ...
13// }
14
15// Use with groups option for subset
16const colorVars = themeToCSSVariables(brand, { groups: ["colors"] });
17const codeVars = themeToCSSVariables(brand, { groups: ["code"] });1import { validateTheme, getBuiltInThemes } from "@theme-kit/core";
2
3const customTheme = defineTheme({
4 name: "custom",
5 tokens: { colors: { primary: "#6366f1" } }, // Missing required colors
6});
7
8const result = validateTheme(customTheme, { themes: getBuiltInThemes() });
9// {
10// valid: false,
11// issues: [
12// { type: "missing", path: "colors.background", message: "Required color token missing" },
13// { type: "missing", path: "colors.foreground", message: "Required color token missing" },
14// ...
15// ]
16// }1import { generateTheme } from "@theme-kit/core";
2
3// Generate complete light/dark pair from one seed color
4const { light, dark } = generateTheme({
5 seed: "#6366f1", // Base brand color
6 family: "indigo", // Family name
7 // Auto-generates: primary, secondary, muted, accent, border, ring
8 // Plus full typography, spacing, radius, shadows scales
9 // And harmonized code tokens for syntax highlighting
10});
11
12console.log(light.name); // "indigo-light"
13console.log(dark.name); // "indigo-dark"
14console.log(light.tokens.code); // Full code token set4Code Tokens
Theme Kit includes a dedicated code token group with 22 semantic tokens for syntax highlighting. Every token maps to a --theme-code-* CSS variable that any highlighter (Shiki, Prism, etc.) can consume — so code blocks re-theme automatically when users switch themes, families, or modes.