Tailwind CSS module for Nuxt applications with zero configuration, CSS nesting support, and configuration viewer
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Extensibility hooks for other Nuxt modules to modify Tailwind configuration and behavior during the build process.
Hook definitions for extending and customizing Tailwind CSS integration.
interface ModuleHooks {
/**
* Called for each Tailwind configuration before merging layers
* @param tailwindConfig - Configuration from current layer/path
*/
'tailwindcss:config': (tailwindConfig: Partial<TWConfig>) => void;
/**
* Called for each resolved configuration from layers and paths
* @param tailwindConfig - Resolved configuration or undefined if failed
* @param configPath - Path to the configuration file
* @param index - Index in the configuration array
* @param configPaths - Array of all configuration paths
*/
'tailwindcss:loadConfig': (
tailwindConfig: Partial<TWConfig> | undefined,
configPath: string,
index: number,
configPaths: string[]
) => void;
/**
* Called with the final resolved configuration including all defaults
* @param tailwindConfig - Complete resolved configuration
* @param oldTailwindConfig - Previous configuration for comparison
*/
'tailwindcss:resolvedConfig': (
tailwindConfig: ReturnType<typeof import('tailwindcss/resolveConfig')>,
oldTailwindConfig: TWConfig | undefined
) => void;
}Modify individual Tailwind configurations before they are merged together.
/**
* Hook called for each configuration before merging
* Use this to modify configurations from specific layers or paths
*/
nuxt.hook('tailwindcss:config', (tailwindConfig) => {
// Modify the configuration
});Usage Examples:
// modules/tailwind-extensions.ts
export default defineNuxtModule({
setup(options, nuxt) {
// Add custom colors to all configurations
nuxt.hook('tailwindcss:config', (config) => {
config.theme = config.theme || {};
config.theme.extend = config.theme.extend || {};
config.theme.extend.colors = {
...config.theme.extend.colors,
brand: {
primary: '#3b82f6',
secondary: '#1e40af',
}
};
});
// Add custom content paths
nuxt.hook('tailwindcss:config', (config) => {
if (Array.isArray(config.content)) {
config.content.push('./modules/**/*.vue');
} else if (config.content && typeof config.content === 'object') {
config.content.files = [
...(config.content.files || []),
'./modules/**/*.vue'
];
}
});
}
});Monitor and modify configurations as they are loaded from files and inline sources.
/**
* Hook called for each loaded configuration
* Provides access to the configuration path and loading context
*/
nuxt.hook('tailwindcss:loadConfig', (config, configPath, index, allPaths) => {
// Process loaded configuration
});Usage Examples:
// modules/config-validator.ts
export default defineNuxtModule({
setup(options, nuxt) {
// Validate configurations as they load
nuxt.hook('tailwindcss:loadConfig', (config, configPath, index, allPaths) => {
if (!config) {
console.warn(`Failed to load Tailwind config from ${configPath}`);
return;
}
// Validate required theme properties
if (!config.theme?.colors) {
console.warn(`No colors defined in ${configPath}`);
}
// Log loading progress
console.info(`Loaded Tailwind config ${index + 1}/${allPaths.length}: ${configPath}`);
});
// Track configuration sources
nuxt.hook('tailwindcss:loadConfig', (config, configPath) => {
if (configPath.includes('node_modules')) {
console.info(`Using third-party Tailwind config: ${configPath}`);
}
});
}
});Access the final, complete Tailwind configuration with all defaults applied.
/**
* Hook called with the final resolved configuration
* This includes all Tailwind defaults and computed values
*/
nuxt.hook('tailwindcss:resolvedConfig', (resolvedConfig, previousConfig) => {
// Access complete configuration
});Usage Examples:
// modules/config-analyzer.ts
export default defineNuxtModule({
setup(options, nuxt) {
// Analyze final configuration
nuxt.hook('tailwindcss:resolvedConfig', (config, oldConfig) => {
// Generate color palette report
const colors = Object.keys(config.theme.colors);
console.info(`Available colors: ${colors.length}`);
// Check for breaking changes
if (oldConfig && oldConfig.theme.colors !== config.theme.colors) {
console.warn('Color palette changed - check for breaking changes');
}
// Validate required utilities
const requiredUtilities = ['flex', 'grid', 'text-center'];
const availableUtilities = config.corePlugins;
// Export configuration for external tools
if (nuxt.options.dev) {
await writeFile(
'tailwind.resolved.json',
JSON.stringify(config, null, 2)
);
}
});
}
});Internal hook for template regeneration (primarily for internal use).
/**
* Internal hook for template regeneration
* Called when configuration templates need to be updated
*/
nuxt.hook('tailwindcss:internal:regenerateTemplates', (data) => {
// Handle template regeneration
});// modules/tailwind-theme.ts
export default defineNuxtModule({
meta: {
name: 'tailwind-theme',
configKey: 'tailwindTheme'
},
setup(options, nuxt) {
// Extend configurations with theme presets
nuxt.hook('tailwindcss:config', (config) => {
if (options.preset === 'corporate') {
config.theme = {
...config.theme,
extend: {
...config.theme?.extend,
colors: {
...config.theme?.extend?.colors,
corporate: {
blue: '#1e3a8a',
gray: '#374151',
green: '#059669'
}
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif']
}
}
};
}
});
}
});// modules/tailwind-validator.ts
export default defineNuxtModule({
setup(options, nuxt) {
const validationRules = options.rules || [];
nuxt.hook('tailwindcss:resolvedConfig', (config) => {
for (const rule of validationRules) {
try {
rule.validate(config);
} catch (error) {
if (rule.level === 'error') {
throw new Error(`Tailwind validation failed: ${error.message}`);
} else {
console.warn(`Tailwind validation warning: ${error.message}`);
}
}
}
});
}
});// modules/tailwind-devtools.ts
export default defineNuxtModule({
setup(options, nuxt) {
if (!nuxt.options.dev) return;
// Track configuration changes
let configHash = '';
nuxt.hook('tailwindcss:resolvedConfig', (config) => {
const newHash = JSON.stringify(config);
if (configHash && configHash !== newHash) {
console.info('🎨 Tailwind configuration updated');
// Notify development tools
nuxt.callHook('dev:tailwind:updated', {
timestamp: Date.now(),
changes: detectChanges(configHash, newHash)
});
}
configHash = newHash;
});
}
});Extend Nuxt's hook types for better TypeScript support:
// types/nuxt.d.ts
declare module 'nuxt/schema' {
interface NuxtHooks {
'custom:tailwind:validated': (config: TWConfig) => void;
}
}
declare module '@nuxt/schema' {
interface NuxtHooks {
'custom:tailwind:validated': (config: TWConfig) => void;
}
}Install with Tessl CLI
npx tessl i tessl/npm-nuxtjs--tailwindcss