Skip to content

Theme API

Creates a theme from design tokens, producing CSS custom properties and a typed vars accessor.

function createTheme(config: ThemeConfig): ThemeResult
interface ThemeConfig {
name?: string // 'default' targets :root; others target [data-theme="<name>"]
colors?: Record<string, Record<string | number, string>>
spacing?: Record<string | number, string>
typography?: {
textSizes?: Record<string, { fontSize: string; lineHeight: string }>
fontWeights?: Record<string, string>
}
borders?: Record<string, string>
shadows?: Record<string, string>
}
interface ThemeResult {
name: string // Theme name
cssText: string // CSS rule string with custom properties
vars: ThemeVars // Type-safe accessor with var(--twc-...) references
}
import { createTheme, injectTheme } from 'typewritingclass/theme'
const { cssText, vars } = createTheme({
name: 'light',
colors: {
primary: { 500: '#3b82f6', 600: '#2563eb' },
surface: { 0: '#ffffff', 100: '#f3f4f6' },
},
})
injectTheme(cssText)
tw.bg(vars.colors.primary[500]) // background-color: var(--twc-color-primary-500)

Injects theme CSS into the document via a <style id="twc-theme"> element.

function injectTheme(cssText: string): void

SSR-safe — no-op when document is undefined. Each call appends to the existing style element. Inject each theme exactly once.


Activates a named theme by setting data-theme on <html>.

function setTheme(name: string): void
setTheme('dark') // <html data-theme="dark">
setTheme('light') // <html data-theme="light">

The matching CSS must be injected via injectTheme() first.

let current = 'light'
function toggleTheme() {
current = current === 'light' ? 'dark' : 'light'
setTheme(current)
}
const saved = localStorage.getItem('theme')
if (saved) {
setTheme(saved)
} else {
setTheme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
}

Token typePatternExample
Color--twc-color-<name>-<shade>--twc-color-blue-500
Spacing--twc-spacing-<key>--twc-spacing-4
Text size--twc-text-<name>-fs / -lh--twc-text-lg-fs
Font weight--twc-font-<name>--twc-font-bold
Border--twc-border-<name>--twc-border-lg
Shadow--twc-shadow-<name>--twc-shadow-md

SubpathKey exports
typewritingclass/theme/colors22 color palettes + white, black, transparent, currentColor
typewritingclass/theme/typographyxs-_9xl text sizes, thin-extrabold weights
typewritingclass/theme/shadowssm, DEFAULT, md, lg, xl, _2xl, inner, none
typewritingclass/theme/bordersnone, sm, DEFAULT, md, lg, xl, _2xl, _3xl, full
typewritingclass/theme/sizesfull, screen, screenH, min, max, fit, auto
typewritingclass/theme/animationsAnimation keyframe presets
typewritingclass/theme/filtersFilter presets
typewritingclass/themeAll theme token exports (barrel)

Most tokens are accessible via string lookups on tw without importing:

tw.bg('blue-500') // no import needed
tw.shadow('lg') // no import needed
tw.rounded('full') // no import needed
tw.font('semibold') // no import needed

Text sizes still require an import:

import { lg, _2xl } from 'typewritingclass/theme/typography'
tw.text(lg)