Configuration

The application theme is normally declared in a root theme.config.ts file. Import defineConfig from @udixio/tailwind: it combines the core theme options with the Tailwind and typography options, then wires the required plugins for you.

ts
// theme.config.ts
import { defineConfig } from '@udixio/tailwind';
import { Variants } from '@udixio/theme';

export default defineConfig({
  sourceColor: '#6750A4',
  variant: Variants.Udixio,
  contrastLevel: 0,

  darkMode: 'class',
  darkSelector: '.dark',
  dynamicSelector: '.dynamic',

  palettes: {
    brand: '#FF5722',
  },

  subThemes: {
    ocean: '#006699',
  },

  fontFamily: {
    expressive: ['Playfair Display', 'Georgia', 'serif'],
    neutral: ['Inter', 'system-ui', 'sans-serif'],
  },
});

The generated stylesheet is written to udixio.generated.css by default. Set outFile when you want it at another path:

ts
// theme.config.ts
import { defineConfig } from '@udixio/tailwind';

export default defineConfig({
  sourceColor: '#6750A4',
  outFile: 'src/styles/udixio.generated.css',
});

Core options

sourceColor

The required source of the theme. A hex string is the recommended configuration form. Advanced code can pass a Color or resolve the value from the current context:

ts
// theme.config.ts
import { defineConfig } from '@udixio/tailwind';

export default defineConfig({
  sourceColor: (context) => (context.isDark ? '#A08EC4' : '#6750A4'),
});

For direct HCT construction, import Color from @udixio/theme:

ts
import { Color } from '@udixio/theme';

const sourceColor = Color.from({ hue: 270, chroma: 36, tone: 49 });

contrastLevel

Adjusts the contrast curves used by semantic tokens. The accepted range is -1 to 1.

ValueEffect
-1Minimum contrast
0Material Design standard (default)
0.5Medium contrast
1Maximum contrast

variant

Selects the palette and token derivation algorithm. defineConfig uses Variants.Udixio by default.

ts
import { defineConfig } from '@udixio/tailwind';
import { Variants } from '@udixio/theme';

export default defineConfig({
  sourceColor: '#6750A4',
  variant: Variants.TonalSpot,
});

See Variants for the built-in algorithms and Variants API for custom variants.

palettes

Adds custom palettes or overrides a standard palette. A palette callback receives the current Context and returns its hue and chroma. When it overrides an existing palette, its optional second argument is the inherited palette recipe for the current context:

ts
// theme.config.ts
import { defineConfig } from '@udixio/tailwind';

export default defineConfig({
  sourceColor: '#6750A4',
  palettes: {
    primary: ({ sourceColor }) => ({
      hue: sourceColor.hue + 30,
      chroma: 60,
    }),
    tertiary: (_context, base) => ({
      ...base!,
      chroma: base!.chroma + 10,
    }),
    neutral: () => ({
      hue: 200,
      chroma: 6,
    }),
    brand: '#FF5722',
  },
});

The tone of a color supplied to a palette is ignored: a palette spans all tones. Hex strings are the simple form; callbacks are the advanced form. The inherited base follows source-color and variant changes, while a string or Color remains an absolute palette replacement.

colors

Adds or transforms semantic color tokens. The definitions belong directly in theme.config.ts; there is no need to declare a separate ColorsConfig variable for a normal application configuration:

ts
// theme.config.ts
import { defineConfig } from '@udixio/tailwind';
import {
  Color,
  avoidBackgroundGap,
  contrastAgainst,
  onColor,
} 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)),
  },
});

A callback transforms the token already supplied by the active variant. It is re-evaluated when the theme context changes. See Colors API for palette colors and tone adjusters.

Tailwind options

These options are provided by @udixio/tailwind and are available at the same level as the core options.

darkMode, darkSelector and dynamicSelector

ts
export default defineConfig({
  sourceColor: '#6750A4',
  darkMode: 'class', // 'class' (default) or 'media'
  darkSelector: '.dark', // default: '.dark'
  dynamicSelector: '.dynamic', // default: '.dynamic'
});

darkMode: 'class' uses darkSelector on an ancestor. darkMode: 'media' uses prefers-color-scheme: dark instead. The dynamic selector scopes CSS variables that can be updated at runtime by React’s ThemeProvider.

subThemes

Defines named themes activated with .theme-{name}. A hex value is the usual form; the plugin uses its hue while keeping the main theme’s visual structure:

ts
export default defineConfig({
  sourceColor: '#6750A4',
  subThemes: {
    ocean: '#006699',
    forest: '#2E7D32',
  },
});

See Sub-themes for the generated selectors and nesting.

responsiveBreakPoints

Adds responsive breakpoints to the generated Tailwind CSS:

ts
export default defineConfig({
  sourceColor: '#6750A4',
  responsiveBreakPoints: {
    tablet: 768,
    '3xl': 1920,
  },
});

resetColors

Defaults to true and removes Tailwind’s default color namespace before the theme colors are emitted. Set it to false to keep utilities such as red-500 alongside the Udixio tokens.

outFile

Controls where the Node/CLI build writes the generated CSS. Relative paths are resolved from the current working directory. The default is udixio.generated.css.

Typography options

fontFamily

Overrides the two conceptual font families:

ts
export default defineConfig({
  sourceColor: '#6750A4',
  fontFamily: {
    expressive: ['Playfair Display', 'Georgia', 'serif'],
    neutral: ['Inter', 'system-ui', 'sans-serif'],
  },
});

fontStyles

Overrides selected role/size values while preserving the rest of the Material type scale:

ts
export default defineConfig({
  sourceColor: '#6750A4',
  fontStyles: {
    display: {
      large: {
        fontSize: 4,
        lineHeight: 4.5,
        fontWeight: 300,
        letterSpacing: -0.02,
      },
    },
    body: {
      large: { lineHeight: 1.75 },
    },
  },
});

See Typography for the generated text-* utilities.