tailwind-resolver
v0.3.4
Published
Resolve Tailwind theme variables into JavaScript objects. Supports Tailwind v4 with future-proof versioning.
Maintainers
Readme
Tailwind Theme Resolver
TypeScript type generation and runtime resolution for Tailwind CSS v4 theme variables.
Transform your Tailwind v4 CSS variables into fully-typed TypeScript interfaces and runtime objects with automatic conflict detection, intelligent nesting, and comprehensive diagnostics.
Table of Contents
- Quick Start
- Core Concepts
- Installation
- Usage
- Configuration
- Advanced Features
- Examples
- Debugging
- Requirements
- Contributing
- License
Quick Start
1. Install:
npm install -D tailwind-resolver2. Configure Vite plugin:
// vite.config.ts
import tailwindcss from '@tailwindcss/vite';
import { tailwindResolver } from 'tailwind-resolver/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
tailwindcss(),
tailwindResolver({
input: 'src/styles.css', // Your Tailwind CSS file
}),
],
});3. Use the generated theme:
import { tailwind } from './generated/tailwindcss';
// Fully typed with autocomplete
const primaryColor = tailwind.variants.default.colors.primary[500];
const darkBackground = tailwind.variants.dark.colors.background;That's it! The plugin automatically generates TypeScript types and runtime objects from your Tailwind CSS variables.
Core Concepts
What It Does
Tailwind Theme Resolver parses your Tailwind CSS v4 files and generates:
- TypeScript Types - Full type safety with autocomplete for all theme properties
- Runtime Objects - JavaScript objects mirroring your CSS variables for use in Canvas, Chart.js, etc.
- Diagnostic Reports - Automatic detection of CSS conflicts and unresolved variables
- Theme Variants - Support for dark mode, custom themes, and CSS selector-based variants
Theme Structure
All Tailwind CSS v4 namespaces are supported:
{
colors: {}, // --color-*
spacing: {}, // --spacing-* (with dynamic calc helper)
fonts: {}, // --font-*
fontSize: {}, // --text-*
fontWeight: {}, // --font-weight-*
tracking: {}, // --tracking-*
leading: {}, // --leading-*
breakpoints: {}, // --breakpoint-*
containers: {}, // --container-*
radius: {}, // --radius-*
shadows: {}, // --shadow-*
insetShadows: {}, // --inset-shadow-*
dropShadows: {}, // --drop-shadow-*
textShadows: {}, // --text-shadow-*
blur: {}, // --blur-*
perspective: {}, // --perspective-*
aspect: {}, // --aspect-*
ease: {}, // --ease-*
animations: {}, // --animate-*
defaults: {}, // --default-*
keyframes: {} // @keyframes
}Generated Files
With default configuration, the plugin generates:
src/generated/tailwindcss/
├── types.ts # TypeScript interfaces
├── theme.ts # Runtime theme objects
├── index.ts # Convenient re-exports
├── conflicts.md # CSS conflict report (if conflicts detected)
├── conflicts.json # Machine-readable conflict data
├── unresolved.md # Unresolved variable report (if any detected)
└── unresolved.json # Machine-readable unresolved dataInstallation
# Bun
bun add -D tailwind-resolver
# pnpm
pnpm add -D tailwind-resolver
# Yarn
yarn add -D tailwind-resolver
# npm
npm install -D tailwind-resolverUsage
Vite Plugin (Build-Time Generation)
Recommended for most projects. Generates types once during build, with hot-reload during development.
Basic Configuration:
import tailwindcss from '@tailwindcss/vite';
import { tailwindResolver } from 'tailwind-resolver/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
tailwindcss(),
tailwindResolver({
input: 'src/styles.css',
}),
],
});Full Configuration:
tailwindResolver({
// Required: Path to CSS file (relative to Vite project root)
input: 'src/styles.css',
// Optional: Output directory (default: auto-detected)
outputDir: 'src/generated/tailwindcss',
// Optional: Resolve @import statements (default: true)
resolveImports: true,
// Optional: Runtime generation control (default: true)
generateRuntime: {
variants: true, // Include theme variants
selectors: true, // Include CSS selectors
files: false, // Exclude file list (production)
variables: false, // Exclude raw variables (production)
reports: {
conflicts: true, // Generate conflict reports
unresolved: true, // Generate unresolved variable reports
},
},
// Optional: Control Tailwind defaults (default: true)
includeDefaults: true,
// Optional: Nesting configuration
nesting: {
colors: { maxDepth: 2 },
default: { maxDepth: 3 },
},
// Optional: Theme overrides
overrides: {
'*': { 'fonts.sans': 'Inter, sans-serif' },
dark: { 'colors.background': '#000000' },
},
// Optional: Debug logging (default: false)
debug: false,
});Usage in Code:
import { dark, defaultTheme, tailwind } from './generated/tailwindcss';
// Use the master tailwind object
const primary = tailwind.variants.default.colors.primary[500];
const darkBg = tailwind.variants.dark.colors.background;
// Or use individual variant exports
const primary2 = defaultTheme.colors.primary[500];
const darkBg2 = dark.colors.background;Runtime API (Dynamic Resolution)
For dynamic scenarios like CLI tools, server-side rendering, or runtime theme switching.
Type-Safe Usage (Recommended):
import type { Tailwind } from './generated/tailwindcss';
import { resolveTheme } from 'tailwind-resolver';
const result = await resolveTheme<Tailwind>({
input: './src/styles.css',
});
// Fully typed with autocomplete
result.variants.default.colors.primary[500];
result.variants.dark.colors.background;
result.selectors.dark; // '[data-theme="dark"]'Note: Generate types using the Vite plugin or CLI before using the runtime API for type safety.
Basic Usage:
import { resolveTheme } from 'tailwind-resolver';
const result = await resolveTheme({
input: './src/styles.css',
});
console.log(result.variants.default.colors.primary[500]);
console.log(result.variants.dark.colors.background);Full Configuration:
const result = await resolveTheme({
// Option 1: CSS file path
input: './src/styles.css',
// Option 2: Raw CSS content
// css: '@theme { --color-primary: blue; }',
// Optional: Base path for @import resolution
basePath: process.cwd(),
// Optional: Resolve @import statements (default: true)
resolveImports: true,
// Optional: Control Tailwind defaults (default: true)
includeDefaults: true,
// Optional: Nesting configuration
nesting: {
colors: { maxDepth: 2 },
default: { maxDepth: 3 },
},
// Optional: Theme overrides
overrides: {
default: { 'fonts.sans': 'Inter' },
},
// Optional: Debug logging (default: false)
debug: false,
});CLI
Generate types without a build tool:
Basic Usage:
bunx tailwind-resolver -i src/styles.cssCommon Options:
# Specify output directory
bunx tailwind-resolver -i src/styles.css -o src/generated
# Types only (no runtime objects)
bunx tailwind-resolver -i src/styles.css --no-runtime
# Include only specific Tailwind defaults
bunx tailwind-resolver -i src/styles.css --include-defaults colors,spacing
# Exclude specific Tailwind defaults
bunx tailwind-resolver -i src/styles.css --exclude-defaults shadows,animations
# Generate only conflict reports
bunx tailwind-resolver -i src/styles.css --reports conflicts
# Debug mode
bunx tailwind-resolver -i src/styles.css --debugAll Options:
-i, --input <path> CSS input file (required)
-o, --output <path> Output directory (default: auto-detected)
-r, --runtime Generate runtime objects (default: true)
--no-runtime Types only
--include-defaults [categories] Include only specified Tailwind defaults (comma-separated)
--exclude-defaults [categories] Exclude specified Tailwind defaults (comma-separated)
--reports [categories] Generate only specified reports (conflicts, unresolved)
--exclude-reports [categories] Exclude specified reports (comma-separated)
-d, --debug Enable debug mode
-h, --help Show helpConfiguration
Tailwind Defaults
Control which Tailwind CSS default theme values are included.
Include All Defaults (Default):
includeDefaults: true;Exclude All Defaults:
includeDefaults: false;Selective Inclusion:
includeDefaults: {
colors: true, // Include default colors
spacing: true, // Include default spacing
fonts: true, // Include default fonts
fontSize: true, // Include default font sizes
fontWeight: true, // Include default font weights
tracking: false, // Exclude tracking
leading: false, // Exclude leading
shadows: false, // Exclude shadows
animations: false, // Exclude animations
// ... 21 categories total
}Disable Specific Defaults via CSS:
Use initial keyword in @theme blocks (Tailwind v4 docs):
@theme {
/* Remove specific values */
--color-lime-*: initial;
--spacing-4: initial;
/* Remove entire categories */
--color-*: initial;
--spacing-*: initial;
/* Custom values are preserved */
--color-primary-500: #3b82f6;
}Combining Approaches:
// Configuration: Include colors and spacing
includeDefaults: {
colors: true,
spacing: true,
shadows: false,
}
// CSS: Remove specific colors
@theme {
--color-lime-*: initial; // Excludes lime from included colors
--color-fuchsia-*: initial; // Excludes fuchsia from included colors
}
// Result: All default colors EXCEPT lime and fuchsiaPriority: CSS initial declarations take precedence over includeDefaults configuration.
Nesting Configuration
Control how CSS variable names are parsed into nested theme structures.
Default Behavior:
Without configuration, all dashes create nesting levels:
--color-tooltip-outline-50: #fff;
/* → colors.tooltip.outline[50] */Limit Nesting Depth:
nesting: {
colors: { maxDepth: 2 },
// --color-brand-primary-hover-500
// → colors.brand.primaryHover500 (2 levels, rest flattened to camelCase)
}Flatten Mode:
Control how parts beyond maxDepth are flattened:
nesting: {
colors: {
maxDepth: 2,
flattenMode: 'camelcase', // Default: blueSkyLight50
// flattenMode: 'literal', // Alternative: 'blue-sky-light-50'
}
}Consecutive Dashes Handling:
nesting: {
colors: {
consecutiveDashes: 'exclude', // Default: skip variables with --
// consecutiveDashes: 'nest', // Treat -- as single -
// consecutiveDashes: 'camelcase',// Convert to camelCase
// consecutiveDashes: 'literal', // Preserve dash
}
}Per-Namespace Configuration:
nesting: {
default: { maxDepth: 1 }, // Apply to all namespaces
colors: { maxDepth: 3 }, // Override for colors
shadows: { maxDepth: 2 }, // Override for shadows
radius: { maxDepth: 0 }, // Completely flat
}Complete Example:
nesting: {
colors: {
maxDepth: 2,
flattenMode: 'literal',
consecutiveDashes: 'camelcase',
}
}
// CSS: --color-tooltip--outline-hover-50
// Step 1: tooltipOutline (consecutive dashes → camelCase)
// Step 2: maxDepth: 2 → colors.tooltipOutline.hover['50']See Nesting Configuration Details for comprehensive documentation.
Theme Overrides
Apply programmatic overrides to theme values without modifying CSS files.
Use Cases:
- Inject external variables (Next.js fonts, plugin variables)
- Fix variant-specific values
- Global customization across all variants
- Quick prototyping
Flat Notation:
overrides: {
default: {
'colors.primary.500': '#custom-blue',
'radius.lg': '0.5rem',
},
dark: {
'colors.background': '#000000',
},
'*': { // Wildcard - applies to all variants
'fonts.sans': 'Inter, sans-serif',
}
}Nested Notation:
overrides: {
default: {
colors: {
primary: {
500: '#custom-blue'
}
},
radius: {
lg: '0.5rem'
}
}
}Detailed Control:
overrides: {
dark: {
'radius.lg': {
value: '0',
force: true, // Apply even for low-confidence conflicts
resolveVars: false // Skip variable resolution
}
}
}Selector Matching:
overrides: {
'dark': {}, // Variant name (preferred)
'[data-theme="dark"]': {}, // CSS selector (verbose)
'default': {}, // Default theme
'base': {}, // Alias for 'default'
'*': {}, // All variants
'themeInter': {}, // .theme-inter → themeInter (camelCase)
}Note: Multi-word variant names are automatically converted to camelCase:
- CSS:
.theme-noto-sans→ Override key:'themeNotoSans'
See Theme Overrides Details for comprehensive documentation.
Report Generation
Control diagnostic report generation.
Enable All Reports (Default):
generateRuntime: {
reports: true,
}Disable All Reports:
generateRuntime: {
reports: false,
}Granular Control:
generateRuntime: {
reports: {
conflicts: true, // CSS conflict reports
unresolved: false, // Unresolved variable reports
}
}CLI:
# Disable all reports
bunx tailwind-resolver -i src/styles.css --no-reports
# Generate only conflict reports
bunx tailwind-resolver -i src/styles.css --reports conflicts
# Exclude unresolved variable reports
bunx tailwind-resolver -i src/styles.css --exclude-reports unresolvedAdvanced Features
CSS Conflict Detection
Automatically detects when CSS rules override CSS variables and ensures runtime theme matches actual rendered styles.
Problem:
.theme-mono {
--radius-lg: 0.45em; /* CSS variable */
.rounded-lg {
border-radius: 0; /* CSS rule - overrides the variable! */
}
}Solution:
The resolver:
- Detects all conflicts between CSS rules and variables
- Applies high-confidence overrides automatically
- Reports complex cases for manual review
Confidence Levels:
- High (auto-applied): Static values, simple selectors
- Medium/Low (manual review): Dynamic values, pseudo-classes, media queries, complex selectors
Generated Reports:
src/generated/tailwindcss/
├── conflicts.md # Human-readable report with recommendations
└── conflicts.json # Machine-readable for CI/CDTerminal Output:
✓ Theme types generated successfully
Generated files:
- src/generated/tailwindcss/types.ts
- src/generated/tailwindcss/theme.ts
- src/generated/tailwindcss/index.ts
⚠ 12 CSS conflicts detected (see src/generated/tailwindcss/conflicts.md)Unresolved Variable Detection
Detects CSS variables with var() references that couldn't be resolved.
Problem:
@theme {
--font-sans: var(--font-inter); /* Injected by Next.js */
--color-accent: var(--tw-primary); /* Tailwind plugin variable */
}Solution:
The resolver categorizes unresolved variables:
- Unknown - May need definition or verification
- External - From plugins, frameworks, or external stylesheets
- Self-referential - Intentionally left unresolved
Generated Reports:
src/generated/tailwindcss/
├── unresolved.md # Human-readable with actionable recommendations
└── unresolved.json # Machine-readable for CI/CDTerminal Output:
ℹ 8 unresolved variables detected (see src/generated/tailwindcss/unresolved.md)Dynamic Spacing Helper
The spacing property is both an object AND a callable function for dynamic calculations.
Static Values:
defaultTheme.spacing.xs; // '0.75rem'
defaultTheme.spacing.base; // '0.25rem'Dynamic Calculations:
defaultTheme.spacing(4); // 'calc(0.25rem * 4)' → 1rem
defaultTheme.spacing(16); // 'calc(0.25rem * 16)' → 4rem
defaultTheme.spacing(-2); // 'calc(0.25rem * -2)' → -0.5remUsage:
<div style={{
padding: defaultTheme.spacing(4), // Same as Tailwind's p-4
margin: defaultTheme.spacing(-2), // Same as Tailwind's -m-2
width: defaultTheme.spacing(64), // Same as Tailwind's w-64
}} />Why: Tailwind generates utilities like p-4, m-8, w-16 using calc(var(--spacing) * N). This helper replicates that behavior for runtime use.
Tailwind Utilities Using Spacing:
- Layout:
inset-<n>,m-<n>,p-<n>,gap-<n> - Sizing:
w-<n>,h-<n>,min-w-<n>,max-w-<n> - Typography:
indent-<n>,border-spacing-<n>,scroll-m-<n>
Note: Requires --spacing-base in your CSS theme.
Type Safety
Full TypeScript type safety with the generated Tailwind interface.
Generated Constant:
import { tailwind } from './generated/tailwindcss';
// Fully typed with autocomplete
tailwind.variants.default.colors.primary[500]; // ✓
tailwind.variants.dark.colors.background; // ✓
tailwind.selectors.dark; // ✓Runtime API:
import type { Tailwind } from './generated/tailwindcss';
import { resolveTheme } from 'tailwind-resolver';
const result = await resolveTheme<Tailwind>({
input: './theme.css',
});
// Same structure, same types
result.variants.default.colors.primary[500]; // ✓
result.variants.dark.colors.background; // ✓
result.selectors.dark; // ✓Autocomplete: Works automatically when output directory is in tsconfig.json includes.
Examples
Chart.js
import { tailwind } from './generated/tailwindcss';
new Chart(ctx, {
data: {
datasets: [
{
backgroundColor: [
tailwind.variants.default.colors.primary[500],
tailwind.variants.dark.colors.secondary[500],
],
},
],
},
});Canvas
import { defaultTheme } from './generated/tailwindcss';
ctx.fillStyle = defaultTheme.colors.background;
ctx.font = `${defaultTheme.fontSize.xl.size} ${defaultTheme.fonts.display}`;Dynamic Theme Switching
import { tailwind } from './generated/tailwindcss';
const currentTheme = isDark
? tailwind.variants.dark
: tailwind.variants.default;
chartInstance.data.datasets[0].backgroundColor =
currentTheme.colors.primary[500];
chartInstance.update();Theme Variants
@theme {
--color-background: #ffffff;
}
[data-theme='dark'] {
--color-background: #1f2937;
}import { dark, defaultTheme, selectors } from './generated/tailwindcss';
console.log(defaultTheme.colors.background); // '#ffffff'
console.log(dark.colors.background); // '#1f2937'
console.log(selectors.dark); // "[data-theme='dark']"Debugging
Enable debug mode to see detailed logging.
Vite:
tailwindResolver({ input: 'src/styles.css', debug: true });CLI:
bunx tailwind-resolver -i src/styles.css --debugRuntime API:
resolveTheme({ input: './theme.css', debug: true });Output:
[Tailwind Theme Resolver] Failed to resolve import: ./components/theme.css
Resolved path: /Users/you/project/src/components/theme.css
Error: ENOENT: no such file or directory
[Overrides] Injected variable: --radius-lg = 0.5rem
[Overrides] Applied to 'default': radius.lg = 0.5remRequirements
- Node.js >= 18 or Bun >= 1.0
- TypeScript >= 5.0 (for type generation)
- Vite >= 5.0 (for Vite plugin only)
Contributing
Issues and pull requests welcome on GitHub.
License
MIT
Appendix
Nesting Configuration Details
Complete documentation for nesting configuration options.
Default Behavior
Without configuration, every dash creates a nesting level:
@theme {
--color-tooltip-outline-50: #fff;
/* → colors.tooltip.outline[50] */
--shadow-elevation-high-focus: 0 0 0;
/* → shadows.elevation.high.focus */
}maxDepth
Limit nesting levels. After the limit, remaining parts are flattened.
Configuration:
nesting: {
colors: {
maxDepth: 2;
}
}Results:
--color-tooltip-outline-50: #fff;
/* Before: colors.tooltip.outline[50] */
/* After: colors.tooltip.outline['50'] (no change - only 3 parts) */
--color-brand-primary-hover-500: #3b82f6;
/* Before: colors.brand.primary.hover[500] */
/* After: colors.brand.primaryHover500 (2 levels, rest flattened) */Special Case - maxDepth: 0:
nesting: { default: { maxDepth: 0 } }
// --color-brand-primary-dark: #000
// → colors.brandPrimaryDark (completely flat)consecutiveDashes
Control how consecutive dashes (--) are processed:
Options:
'exclude'(default, matches Tailwind v4) - Skip variables with--'nest'- Treat--as single-'camelcase'- Convert--to camelCase boundary'literal'- Preserve--in keys
Configuration:
nesting: {
colors: {
consecutiveDashes: 'camelcase';
}
}Results:
--color-button--primary: #fff;
/* 'exclude' (default): Not included */
/* 'nest': colors.button.primary */
/* 'camelcase': colors.buttonPrimary */
/* 'literal': colors['button-'].primary */flattenMode
Control how parts beyond maxDepth are flattened:
Options:
'camelcase'(default) - Flatten to camelCase'literal'- Flatten to kebab-case string key
Configuration:
nesting: {
colors: {
maxDepth: 2,
flattenMode: 'literal'
}
}Results:
--color-blue-sky-light-50: #e0f2fe;
/* flattenMode: 'camelcase' (default) */
/* → colors.blue.skyLight50 */
/* flattenMode: 'literal' */
/* → colors.blue['sky-light-50'] */Note: Only applies when maxDepth is reached.
Combining Options
nesting: {
colors: {
maxDepth: 2,
consecutiveDashes: 'camelcase',
flattenMode: 'literal',
}
}--color-tooltip--outline-hover-50: #fff;
/* Step 1: tooltipOutline (consecutive dashes → camelCase) */
/* Step 2: maxDepth: 2 → colors.tooltipOutline.hover['50'] */Per-Namespace Configuration
nesting: {
colors: { maxDepth: 3 }, // Deep nesting
shadows: { maxDepth: 2 }, // Moderate nesting
spacing: { maxDepth: 1 }, // Flat structure
radius: { consecutiveDashes: 'camelcase' },
}Global Default
nesting: {
default: { maxDepth: 1 }, // Apply to all namespaces
colors: { maxDepth: 3 }, // Override for colors
}DEFAULT Key for Conflicts
When both scalar and nested variables exist at the same path, the scalar moves to DEFAULT:
@theme {
--color-card: blue;
--color-card-foreground: white;
}// Result:
{
colors: {
card: {
DEFAULT: 'blue',
foreground: 'white'
}
}
}Works in Any Order:
/* Nested first, then scalar */
--color-card-foreground: white;
--color-card: blue;
/* Same result: { card: { DEFAULT: 'blue', foreground: 'white' } } */With Color Scales:
--color-blue-500: #3b82f6;
--color-blue-600: #2563eb;
--color-blue: #1d4ed8;// Result:
{
blue: {
DEFAULT: '#1d4ed8',
500: '#3b82f6',
600: '#2563eb'
}
}Use Cases
1. Consistent Flat Structure:
nesting: { default: { maxDepth: 0 } }
// All variables flattened:
// --color-brand-primary-500 → colors.brandPrimary5002. BEM-Style Naming:
nesting: {
default: {
maxDepth: 1,
consecutiveDashes: 'camelcase'
}
}
// --color-button--primary → colors.buttonPrimary
// --color-input--error → colors.inputError3. Controlled Depth by Category:
nesting: {
colors: { maxDepth: 3 }, // Deep color scales
shadows: { maxDepth: 2 }, // Moderate shadow variants
radius: { maxDepth: 1 }, // Flat radius values
}CLI Flags
# Limit nesting depth globally
bunx tailwind-resolver -i src/styles.css --nesting-max-depth 2
# Control consecutive dashes
bunx tailwind-resolver -i src/styles.css --nesting-consecutive-dashes camelcase
# Control flatten mode
bunx tailwind-resolver -i src/styles.css --nesting-flatten-mode literal
# Combine options
bunx tailwind-resolver -i src/styles.css \
--nesting-max-depth 2 \
--nesting-consecutive-dashes nest \
--nesting-flatten-mode literalNote: CLI flags apply globally to all namespaces. For per-namespace control, use Vite plugin or Runtime API.
Theme Overrides Details
Complete documentation for theme overrides.
When to Use Overrides
- Inject external variables - Provide values for Next.js fonts, Tailwind plugins, or external sources
- Fix variant-specific values - Override dark mode or custom theme properties
- Global customization - Apply consistent values across all variants
- Quick prototyping - Test theme changes without editing CSS
Syntax Options
Flat Notation (Dot-Separated Paths):
overrides: {
default: {
'colors.primary.500': '#custom-blue',
'radius.lg': '0.5rem',
'fonts.sans': 'Inter, sans-serif'
}
}Nested Notation:
overrides: {
default: {
colors: {
primary: {
500: '#custom-blue'
}
},
radius: {
lg: '0.5rem'
}
}
}Mix and Match:
overrides: {
default: {
'colors.primary.500': '#custom-blue',
radius: { lg: '0.5rem' }
}
}Selector Matching
Variant Names (Recommended):
overrides: {
'dark': { 'colors.background': '#000' },
'themeInter': { 'fonts.sans': 'Inter' }, // .theme-inter → themeInter
}CSS Selectors (Verbose):
overrides: {
'[data-theme="dark"]': { 'colors.background': '#000' },
}Special Keys:
overrides: {
'default': {}, // Default theme
'base': {}, // Alias for 'default'
'*': {}, // All variants (wildcard)
}Important: Variant names are automatically converted from kebab-case to camelCase:
- CSS:
.theme-inter→ Override key:'themeInter' - CSS:
.theme-noto-sans→ Override key:'themeNotoSans'
Detailed Control
overrides: {
dark: {
'radius.lg': {
value: '0',
force: true, // Apply even for low-confidence conflicts
resolveVars: false // Skip variable resolution (post-resolution only)
}
}
}Common Use Cases
1. Injecting External Variables:
overrides: {
default: {
'fonts.sans': 'var(--font-inter)', // Next.js font
'colors.primary': 'var(--tw-primary)' // Tailwind plugin
}
}2. Variant-Specific Overrides:
overrides: {
dark: {
'colors.background': '#000000',
'colors.foreground': '#ffffff'
},
compact: {
'radius.lg': '0',
'spacing.base': '0.125rem'
}
}3. Global Overrides:
overrides: {
'*': {
'fonts.sans': 'Inter, -apple-system, BlinkMacSystemFont, sans-serif',
'fonts.mono': 'JetBrains Mono, Consolas, monospace'
}
}4. Prototyping:
overrides: {
default: {
'colors.primary.500': '#ff6b6b',
'radius.lg': '1rem'
}
}How It Works
Two-phase approach:
Pre-resolution (Variable Injection)
- Injects synthetic CSS variables before resolution
- Allows overrides to participate in
var()resolution - Applied to:
'default','base','*'selectors
Post-resolution (Theme Mutation)
- Directly mutates resolved theme objects
- Overrides final computed values
- Applied to: all selector types
Debug Mode
tailwindResolver({
input: 'src/styles.css',
debug: true,
overrides: {
default: { 'radius.lg': '0.5rem' },
},
});Output:
[Overrides] Injected variable: --radius-lg = 0.5rem
[Overrides] Injected 1 variables for 'default'
[Overrides] Applied to 'default': radius.lg = 0.5rem
[Overrides] Summary for 'default': 1 applied, 0 skippedTypeScript Configuration
Ensure the output directory is included in tsconfig.json:
{
"include": ["src/**/*"],
"compilerOptions": {
"skipLibCheck": true
}
}If you find this helpful, follow me on X @mrstern_
