createTokens
Design token registry with hierarchical collections, alias resolution, and namespace support.
Usage
The createTokens composable allows you to define a collection of design tokens, which can be primitive values or aliases that reference other tokens. It provides a context for resolving these tokens, making it easy to access design values throughout your application.
import { createTokens } from '@vuetify/v0'
// Default behavior (depth = Infinity): fully flatten nested objects
const tokens = createTokens({
color: {
primary: '#3b82f6',
secondary: '#64748b',
info: '{primary}'
},
radius: {
sm: '4px',
md: '8px',
},
})
tokens.resolve('color.primary') // '#3b82f6'
tokens.resolve('color.info') // '#3b82f6' (alias resolved)
tokens.resolve('radius.md') // '8px'
const features = createTokens({
dark: true,
rtl: { value: true, variation: 'toggle' },
}, { flat: true })
// With flat: true, nested objects are kept as-is at their base id
features.resolve('rtl') // { value: true, variation: 'toggle' }Context / DI
Use createTokensContext to share a token registry across a component tree:
import { createTokensContext } from '@vuetify/v0'
export const [useTokens, provideTokens, tokens] =
createTokensContext({
namespace: 'my:tokens',
tokens: {
colors: {
primary: '#3b82f6',
secondary: '{colors.primary}', // alias
},
},
})
// In parent component
provideTokens()
// In child component
const tokens = useTokens()
tokens.resolve('colors.primary') // '#3b82f6'Options
createTokens
| Option | Type | Default | Notes |
|---|---|---|---|
flat | boolean | false | Keep nested objects as-is at their base key instead of flattening |
prefix | string | — | Prepend a string to every token ID on registration (e.g. 'color.') |
createTokensContext
Accepts all createTokens options plus:
| Option | Type | Default | Notes |
|---|---|---|---|
namespace | string | — | DI namespace string (e.g. 'my:tokens') |
tokens | TokenCollection | — | Initial token collection registered when the context is created |
Architecture
createTokens extends createRegistry and powers token-based systems:
Reactivity
createTokens uses minimal reactivity like its parent createRegistry. Token resolution is cached but not reactive.
For reactive theming Use useTheme which builds on createTokens with proper reactivity for theme switching.
Examples
Design Token Explorer
A design system with four token categories — color palettes, semantic aliases, spacing, and radius — split across two files:
| File | Role |
|---|---|
tokens.ts | Defines the token collection with nested color scales and semantic aliases |
design-system.vue | Explorer UI with category tabs, search, and an alias resolver |
Key patterns:
Nested objects flatten to dot-notation IDs:
color.blue.500,spacing.mdAlias syntax
{color.blue.500}references other tokens —resolve()follows the chainisAlias()distinguishes alias references from direct valuesClick any token to resolve it in the Alias Resolver panel
Frequently Asked Questions
They control how nested objects are processed:
| Option | Behavior | Token IDs |
|---|---|---|
depth: Infinity (default) | Recursively flatten all nested objects | color.primary, color.secondary |
flat: true | Keep objects as-is at their base key | rtl → { value: true, ... } |
// depth: Infinity (default) - flattens nested objects
const colors = createTokens({
color: { primary: '#3b82f6', secondary: '#64748b' }
})
colors.resolve('color.primary') // '#3b82f6'
colors.resolve('color') // undefined - 'color' itself isn't a token
// flat: true - preserves object structure
const features = createTokens({
rtl: { value: true, variation: 'toggle' }
}, { flat: true })
features.resolve('rtl') // { value: true, variation: 'toggle' }Use flat: true when your token values are objects you want to keep intact (e.g., feature flags with metadata).
Circular aliases will cause infinite recursion. The resolver doesn’t detect cycles:
// DON'T DO THIS - infinite loop
const tokens = createTokens({
a: '{b}',
b: '{a}', // circular reference
})
tokens.resolve('a') // Maximum call stack exceededDesign your token hierarchy as a directed acyclic graph (DAG). The Design Tokens spec↗ recommends keeping alias chains shallow:
No. Token values are static at registration time. For reactive design systems, resolve tokens into refs:
// Static tokens
const tokens = createTokens({
color: { primary: '#3b82f6', dark: '#1e3a8a' }
})
// Reactive usage
const isDark = ref(false)
const primaryColor = computed(() =>
tokens.resolve(isDark.value ? 'color.dark' : 'color.primary')
)For fully reactive theming, see useTheme which builds on createTokens.
No. Aliases only resolve within the same createTokens instance:
const colors = createTokens({ primary: '#3b82f6' })
const spacing = createTokens({ gap: '{primary}' }) // Won't resolve - different instance
spacing.resolve('gap') // '{primary}' - returned as literal stringTo share tokens across collections, use a single unified token set or compose at the application level.
Use register and unregister inherited from createRegistry:
const tokens = createTokens({
color: { primary: '#3b82f6' }
})
// Update a token
tokens.unregister('color.primary')
tokens.register({ id: 'color.primary', value: '#ef4444' })
tokens.resolve('color.primary') // '#ef4444'For theme switching, consider useTheme which handles this pattern with proper reactivity.
Alias resolution is recursive string replacement—each {alias} triggers another resolve() call. For deep chains:
token → alias1 → alias2 → alias3 → value
↓ ↓ ↓
resolve resolve resolveKeep alias chains shallow (2-3 levels max) for predictable performance. If you need deep composition, resolve intermediate values at build time.
createTokens is inspired by the Design Tokens Community Group specification↗. Key alignments:
| Spec Concept | createTokens |
|---|---|
| Token value | register({ id, value }) |
Alias syntax {path.to.token} | Supported via resolve() |
| Nested groups | Flattened with dot notation |
The spec is still in draft, so createTokens focuses on the stable patterns. For CSS custom property output, pair with useTheme which handles CSS variable generation.
Benchmarks
Every operation is profiled across multiple dataset sizes to measure real-world throughput. Each benchmark is assigned a performance tier—good, fast, blazing, or slow—and groups are scored by averaging their individual results so you can spot bottlenecks at a glance. This transparency helps you make informed decisions about which patterns scale for your use case. Learn more in the benchmarks guide.