TailwindPlugin

TailwindPlugin transforms computed color and typography tokens into CSS. It generates the static @theme block (Tailwind build-time) and the dynamic @layer theme block (runtime, scoped to .dynamic).

When using defineConfig from @udixio/tailwind, TailwindPlugin is wired automatically — you never instantiate it directly. All options are passed flat into defineConfig. This page covers the internals.

Direct instantiation

ts
import { FontPlugin, loader } from '@udixio/theme';
import { TailwindPlugin } from '@udixio/tailwind';

const api = await loader({
  sourceColor: '#6750A4',
  plugins: [
    new FontPlugin(),
    new TailwindPlugin({ darkMode: 'class', darkSelector: '.dark' }),
  ],
});
await api.load();

const css = api.plugins.getPlugin(TailwindPlugin).getInstance().outputCss;

Generating the static CSS programmatically

generateStaticThemeCss(config) returns, as a string, exactly what the udixio-theme CLI and the bundler plugins write to udixio.generated.css — without touching the filesystem. Use it from your own build script when neither fits (custom pipelines, several themes emitted at once):

ts
import { writeFileSync } from 'node:fs';
import { generateStaticThemeCss } from '@udixio/tailwind';
import config from './theme.config';

writeFileSync('src/udixio.generated.css', await generateStaticThemeCss(config));

An optional second argument (api) => void runs before the load, for palette or context overrides. For the colors-only CSS used at runtime / SSR, use generateThemeCss from @udixio/ui-react instead.

Options reference

OptionTypeDefaultDescription
darkMode'class' | 'media''class'Dark mode strategy
darkSelectorstring'.dark'CSS class/selector that activates dark mode
dynamicSelectorstring'.dynamic'Selector that receives live CSS variables
subThemesRecord<string, string | Color | number>—Named color variants (see Sub-themes)
responsiveBreakPointsRecord<string, number>{ lg: 1.125 }Additional Tailwind breakpoints
outFilestringudixio.generated.cssOutput path for the generated stylesheet in Node/CLI mode
resetColorsbooleantrueReset Tailwind’s default color namespace before emitting theme colors
ssrbooleanfalseEmit browser-compatible CSS without filesystem writes

CSS structure

The plugin generates three distinct blocks on every api.load():

css
/* 1. Static — Tailwind build-time values */
@theme {
  --color-primary: #6750a4;
  --color-surface: #fffbfe;
  /* … all tokens */
}

/* 2. Dynamic light — runtime, scoped to .dynamic */
@layer theme {
  .dynamic {
    --color-primary: #6750a4;
    --color-surface: #fffbfe;
  }
}

/* 3. Dynamic dark — runtime, scoped to .dark .dynamic */
@layer theme {
  .dark .dynamic,
  .dark.dynamic {
    --color-primary: #d0bcff;
    --color-surface: #1c1b1f;
  }
}

For darkMode: 'media', block 3 uses @media (prefers-color-scheme: dark) instead of a class selector.

dynamicSelector

The dynamic selector is the scope boundary for runtime updates. Only elements inside .dynamic (or whatever value you configure) receive live variable updates when ThemeProvider reinjects the <style> tag.

ts
new TailwindPlugin({ dynamicSelector: '.my-app' });
html
<div class="my-app">
  <!-- lives in the live-update scope -->
</div>

Elements outside this selector still get Tailwind values from the static @theme block, but those reflect the build-time snapshot only.

responsiveBreakPoints

Adds custom breakpoints to the generated CSS:

ts
new TailwindPlugin({
  responsiveBreakPoints: {
    '3xl': 1920,
    tablet: 768,
  },
});

outFile

In non-browser environments, outFile controls where the generated stylesheet is written. Relative paths are resolved from the current working directory. The plugin writes the generated file; it does not append to an existing stylesheet.

ts
new TailwindPlugin({
  outFile: './src/styles/udixio.generated.css',
});

Accessing output from onLoad

ts
class MyPlugin extends PluginImplAbstract<{}> {
  onLoad() {
    const tw = this.api.plugins.getPlugin(TailwindPlugin).getInstance();
    console.log(tw.outputCss); // the full generated CSS string
  }
}