Color tokens
The system generates semantic tokens from palettes. Each token has a tone optimized for the configured light/dark mode and contrast level.
Usage in Tailwind CSS
Tokens are exposed as CSS variables and Tailwind utility classes:
<!-- Surface background -->
<div class="bg-surface text-on-surface">...</div>
<!-- Primary button -->
<button class="bg-primary text-on-primary">Action</button>
<!-- Secondary container -->
<div class="bg-secondary-container text-on-secondary-container">...</div>Token reference
Surfaces
Surfaces form the layers of the interface. They range from darkest (surfaceContainerLowest) to lightest (surfaceContainerHighest) in light mode, and inversely in dark mode.
| Token | Tailwind class | Usage |
|---|---|---|
surface | bg-surface | Main background |
surfaceDim | bg-surface-dim | Slightly dimmed surface |
surfaceBright | bg-surface-bright | Slightly brightened surface |
surfaceContainerLowest | bg-surface-container-lowest | Layer 0 (lowest) |
surfaceContainerLow | bg-surface-container-low | Layer 1 |
surfaceContainer | bg-surface-container | Layer 2 (cards, dialogs) |
surfaceContainerHigh | bg-surface-container-high | Layer 3 |
surfaceContainerHighest | bg-surface-container-highest | Layer 4 (highest) |
onSurface | text-on-surface | Primary text on surface |
onSurfaceVariant | text-on-surface-variant | Secondary text on surface |
outline | border-outline | Visible borders |
outlineVariant | border-outline-variant | Subtle dividers |
inverseSurface | bg-inverse-surface | Inverted surface (snackbar, tooltip) |
inverseOnSurface | text-inverse-on-surface | Text on inverted surface |
Primary
| Token | Tailwind class | Usage |
|---|---|---|
primary | bg-primary | Main actions, CTAs |
onPrimary | text-on-primary | Text on primary |
primaryContainer | bg-primary-container | Soft colored areas |
onPrimaryContainer | text-on-primary-container | Text on primaryContainer |
inversePrimary | text-inverse-primary | Link on inverted surface |
Secondary
| Token | Tailwind class | Usage |
|---|---|---|
secondary | bg-secondary | Secondary accents |
onSecondary | text-on-secondary | Text on secondary |
secondaryContainer | bg-secondary-container | Chips, badges |
onSecondaryContainer | text-on-secondary-container | Text on secondaryContainer |
Tertiary
| Token | Tailwind class | Usage |
|---|---|---|
tertiary | bg-tertiary | Additional accents |
onTertiary | text-on-tertiary | Text on tertiary |
tertiaryContainer | bg-tertiary-container | Soft tertiary areas |
onTertiaryContainer | text-on-tertiary-container | Text on tertiaryContainer |
Error
| Token | Tailwind class | Usage |
|---|---|---|
error | bg-error | Error state |
onError | text-on-error | Text on error |
errorContainer | bg-error-container | Soft error area |
onErrorContainer | text-on-error-container | Text on errorContainer |
Aliases
These tokens are aliases for Material Design compatibility:
| Alias | Points to |
|---|---|
background | surface |
onBackground | onSurface |
surfaceVariant | surfaceContainerHighest |
surfaceTint | primary |
Raw CSS variables
Variables are generated as --color-{token} with camelCase converted to kebab-case. The build output registers them in Tailwind’s @theme block; the runtime layer scopes live values to the configured dynamic selector:
@theme {
--color-primary: #6750a4;
--color-on-primary: #ffffff;
--color-primary-container: #eaddff;
--color-surface: #fef7ff;
/* … */
}
@layer theme {
.dynamic {
--color-primary: #6750a4;
--color-on-primary: #ffffff;
/* … */
}
.dark .dynamic {
--color-primary: #d0bcff;
--color-on-primary: #381e72;
/* … */
}
}Custom color tokens (Udixio variant)
With variant: Variants.Udixio and custom palettes, these tokens are generated for each {name} palette:
--color-{name}
--color-on-{name}
--color-{name}-container
--color-on-{name}-container<!-- Example with "brand" palette -->
<div class="bg-brand text-on-brand">...</div>
<div class="bg-brand-container text-on-brand-container">...</div>Adding custom tokens
Add custom semantic tokens directly to theme.config.ts. A token can be a static hex value, a dynamic Color, or a transformation of the token already provided by the active variant:
// theme.config.ts
import { defineConfig } from '@udixio/tailwind';
import {
Color,
contrastAgainst,
onColor,
avoidBackgroundGap,
} from '@udixio/theme';
export default defineConfig({
sourceColor: '#6750A4',
colors: {
highlight: Color.fromPalette('tertiary', {
tone: () => 40,
adjustTone: [contrastAgainst('surface', 3), avoidBackgroundGap()],
}),
onHighlight: Color.fromPalette('tertiary', {
adjustTone: onColor('highlight', 4.5),
}),
surface: (color) => color.withTone(Math.min(100, color.tone + 2)),
},
});See Colors API for every adjuster and how to write your own.
Reading tokens from the API
A token is a Color, read as a value — each access resolves against the current dark mode and contrast level:
const api = await loader(config);
await api.load();
// With sourceColor '#6750A4' and the default variant:
const primary = api.colors.get('primary');
primary.hex; // "#655789"
primary.tone; // 40.3 in light mode, 80 in dark
primary.hue; // 299.4
primary.chroma; // 32.2
primary.rgb; // { r: 101, g: 87, b: 137 }
primary.argb; // 4284831625Derivations remain dynamic. They are evaluated again when the source token is resolved for another context or variant:
primary.withTone(90); // the same hue and chroma, at tone 90
primary.rotate(55); // hue shifted by 55°, normalised over 360
primary.scaleChroma(0.5);
primary.contrastWith(api.colors.get('surface')); // 6.08See Color for the constructors.