Skip to main content

@ttoss/theme2

Type-safe design tokens engine for the ttoss ecosystem. Two-layer token architecture (core → semantic), built-in themes, adapters for Chakra UI v3 / Tailwind CSS / CSS custom properties, and a framework-agnostic runtime for theme/mode switching with SSR support.

Installation

pnpm add @ttoss/theme2

Quick Start

Chakra UI v3

import { themes, toChakraTheme } from '@ttoss/theme2';
import { ChakraProvider, createSystem, defaultConfig } from '@chakra-ui/react';

const system = createSystem(defaultConfig, toChakraTheme(themes.bruttal));

export const App = ({ children }) => (
<ChakraProvider value={system}>{children}</ChakraProvider>
);

CSS Custom Properties + Runtime

import { themes, toCssVars, createThemeRuntime } from '@ttoss/theme2';

// Generate CSS for each theme
const defaultCss = toCssVars(themes.default).toCssString();
const bruttalCss = toCssVars(themes.bruttal, {
themeId: 'bruttal',
}).toCssString();

// Switch themes at runtime (client-only)
const runtime = createThemeRuntime({
defaultTheme: 'bruttal',
defaultMode: 'system',
});
runtime.setTheme('oca');
runtime.setMode('dark');

Token Architecture

ThemeTokensV2
├── core — raw primitives (colors, fonts, spacing, radii, motion, etc.)
└── semantic — stable aliases via {core.*} references (the only layer components consume)

Components must never consume core tokens directly. Semantic tokens must only contain {core.*} references, not raw values.

Creating Themes

import { createTheme, defaultTheme } from '@ttoss/theme2';

const myTheme = createTheme({
overrides: {
core: {
colors: { brand: { main: '#FF4500', accent: '#D4A017' } },
},
},
});

// Theme inheritance
const child = createTheme({
base: myTheme,
overrides: { core: { radii: { md: '16px' } } },
});

createTheme deep-merges overrides into the base and returns a fully independent clone — mutations never propagate between themes.

Adapters

toChakraTheme(theme) → Chakra UI v3

import { createSystem, defaultConfig } from '@chakra-ui/react';
const system = createSystem(defaultConfig, toChakraTheme(themes.bruttal));

Returns { theme: { tokens, semanticTokens, textStyles }, breakpoints }.

toTailwindTheme(theme) → Tailwind CSS

const tw = toTailwindTheme(themes.default);
const css = tw.toCssString(); // :root { --tt-color-brand-main: #292C2a; ... }
// tw.config — Tailwind theme config referencing CSS vars

toCssVars(theme, options?) → CSS Custom Properties

// :root baseline
toCssVars(themes.default).toCssString();

// Scoped by theme
toCssVars(themes.bruttal, { themeId: 'bruttal' }).toCssString();
// → [data-tt-theme="bruttal"] { --tt-color-brand-main: #0A0A0A; ... }

// Scoped by theme + mode
toCssVars(darkTheme, {
themeId: 'bruttal',
mode: 'dark',
colorScheme: 'dark',
}).toCssString();
// → [data-tt-theme="bruttal"][data-tt-mode="dark"] { color-scheme: dark; ... }

Runtime

createThemeRuntime(config?)

Framework-agnostic, client-only. Manages data-tt-theme / data-tt-mode attributes, color-scheme style, localStorage persistence, and prefers-color-scheme listener.

const runtime = createThemeRuntime({
defaultTheme: 'bruttal',
defaultMode: 'system',
});

runtime.getState(); // { themeId, mode, resolvedMode }
runtime.setTheme('oca');
runtime.setMode('dark');
runtime.subscribe(console.log);
runtime.destroy();

SSR — Preventing Theme Flash

// Next.js app/layout.tsx
import { getThemeScriptContent } from '@ttoss/theme2';

export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<script dangerouslySetInnerHTML={{ __html: getThemeScriptContent() }} />
</head>
<body>{children}</body>
</html>
);
}

React Integration

Import from @ttoss/theme2/react (React is an optional peer dependency):

import { ThemeProvider, ThemeScript, useTheme } from '@ttoss/theme2/react';

export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<ThemeScript defaultTheme="bruttal" />
</head>
<body>
<ThemeProvider defaultTheme="bruttal">{children}</ThemeProvider>
</body>
</html>
);
}

// In any component inside ThemeProvider
const { themeId, mode, resolvedMode, setTheme, setMode } = useTheme();

Built-in Themes

ThemePalette
defaultNeutral baseline, system fonts, gray palette
bruttalBold contrasts, dark neutrals, zero radii
ocaNatural greens, organic warmth
auroraCool-toned purples, rounded surfaces
terraWarm amber/olive, grounded feel
neonVibrant accents, dark backgrounds