Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,35 @@ return (

## Tailwind

### Using the Tailwind Plugin (Recommended)

The easiest way to integrate react-mcu with Tailwind CSS is to use the plugin:

```css
@import "tailwindcss";
@plugin "react-mcu/tailwind-plugin";
```

This automatically maps all `--mcu-*` CSS variables to Tailwind theme colors, so you can use classes like `bg-primary`, `text-on-surface`, `bg-surface-container`, etc.

#### With Custom Colors

If you're using custom colors, pass them to the plugin:

```css
@import "tailwindcss";
@plugin "react-mcu/tailwind-plugin" {
customColors:
[ "myCustomColor1",
"myCustomColor2",
"myCustomColor3"];
}
```

This enables classes like `bg-myCustomColor1`, `text-on-myCustomColor1`, `bg-myCustomColor1-container`, `bg-myCustomColor1-500`, etc.

### Manual Setup (Alternative)

Compatible through [theme variables](https://tailwindcss.com/docs/theme):

https://github.com/abernier/react-mcu/blob/688c789e322ed3858b51389b33eb7ea342bba81e/src/tailwind.css#L3-L186
Expand Down
39 changes: 39 additions & 0 deletions examples/tailwind-plugin-usage.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Example usage of the react-mcu Tailwind plugin
*
* This file demonstrates how to use the plugin with custom colors.
*/

@import "tailwindcss";

/* Use the plugin without custom colors */
@plugin "react-mcu/tailwind-plugin";

/* OR with custom colors: */
/*
@plugin "react-mcu/tailwind-plugin" {
customColors: ["myCustomColor1", "myCustomColor2", "myCustomColor3"];
}
*/

/**
* Available color classes:
*
* - bg-primary, text-on-primary, bg-primary-container, text-on-primary-container
* - bg-secondary, text-on-secondary, bg-secondary-container, text-on-secondary-container
* - bg-tertiary, text-on-tertiary, bg-tertiary-container, text-on-tertiary-container
* - bg-error, text-on-error, bg-error-container, text-on-error-container
* - bg-surface, text-on-surface, bg-surface-dim, bg-surface-bright
* - bg-surface-container-lowest, bg-surface-container-low, bg-surface-container
* - bg-surface-container-high, bg-surface-container-highest
* - bg-background, text-on-background
* - bg-outline, bg-outline-variant
*
* Shades (50-950):
* - bg-primary-500, bg-secondary-200, bg-tertiary-700
* - bg-error-100, bg-neutral-600, bg-neutral-variant-400
*
* Custom colors (when configured):
* - bg-myCustomColor1, text-on-myCustomColor1, bg-myCustomColor1-container
* - bg-myCustomColor1-500, bg-myCustomColor1-300, etc.
*/
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./tailwind.css": "./dist/tailwind.css"
"./tailwind.css": "./dist/tailwind.css",
"./tailwind-plugin": {
"types": "./dist/tailwind-plugin.d.ts",
"import": "./dist/tailwind-plugin.js"
}
},
"homepage": "https://github.com/abernier/react-mcu",
"bugs": {
Expand All @@ -26,7 +30,9 @@
"license": "MIT",
"files": [
"dist",
"src/tailwind.css"
"src/tailwind.css",
"src/tailwind-plugin.js",
"src/tailwind-plugin.d.ts"
],
"type": "module",
"packageManager": "pnpm@10.27.0",
Expand Down Expand Up @@ -58,7 +64,7 @@
"vitest": "^4.0.16"
},
"scripts": {
"build": "tsup",
"build": "tsup && node scripts/post-build.js",
"lgtm": "pnpm run build && pnpm run check-format && pnpm run check-exports && pnpm run typecheck && pnpm run test",
"typecheck": "tsc",
"test": "vitest run",
Expand Down
5 changes: 5 additions & 0 deletions scripts/post-build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { copyFileSync } from "fs";

// Copy tailwind-plugin files after build
copyFileSync("src/tailwind-plugin.d.ts", "dist/tailwind-plugin.d.ts");
console.log("✓ Copied tailwind-plugin.d.ts to dist/");
39 changes: 39 additions & 0 deletions src/tailwind-plugin.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* react-mcu Tailwind CSS Plugin Type Definitions
*/

export interface McuPluginOptions {
/**
* Array of custom color names to include in the plugin
* @example ["myCustomColor1", "myCustomColor2"]
*/
customColors?: string[];
}

/**
* react-mcu Tailwind CSS Plugin
*
* This plugin automates the integration of Material Color Utilities (MCU)
* with Tailwind CSS by mapping --mcu-* CSS variables to Tailwind theme colors.
*
* @param options - Plugin options
* @returns Tailwind plugin configuration
*
* @example
* // In your CSS file:
* @import "tailwindcss";
* @plugin "react-mcu/tailwind-plugin";
*
* @example
* // With custom colors:
* @plugin "react-mcu/tailwind-plugin" {
* customColors: ["myCustomColor1", "myCustomColor2"];
* }
*/
export default function mcuPlugin(options?: McuPluginOptions): {
theme: {
extend: {
colors: Record<string, string>;
};
};
};
157 changes: 157 additions & 0 deletions src/tailwind-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/**
* react-mcu Tailwind CSS Plugin
*
* This plugin automates the integration of Material Color Utilities (MCU)
* with Tailwind CSS by mapping --mcu-* CSS variables to Tailwind theme colors.
*
* @param {Object} options - Plugin options
* @param {string[]} options.customColors - Array of custom color names to include
* @returns {Object} Tailwind plugin configuration
*
* @example
* // In your CSS file:
* @import "tailwindcss";
* @plugin "react-mcu/tailwind-plugin";
*
* @example
* // With custom colors:
* @plugin "react-mcu/tailwind-plugin" {
* customColors: ["myCustomColor1", "myCustomColor2"];
* }
*/
export default function mcuPlugin(options = {}) {
const { customColors = [] } = options;

// Base MCU color mappings
const baseColors = {
// Background and Surface colors
background: "var(--mcu-background)",
"on-background": "var(--mcu-on-background)",
surface: "var(--mcu-surface)",
"surface-dim": "var(--mcu-surface-dim)",
"surface-bright": "var(--mcu-surface-bright)",
"surface-container-lowest": "var(--mcu-surface-container-lowest)",
"surface-container-low": "var(--mcu-surface-container-low)",
"surface-container": "var(--mcu-surface-container)",
"surface-container-high": "var(--mcu-surface-container-high)",
"surface-container-highest": "var(--mcu-surface-container-highest)",
"on-surface": "var(--mcu-on-surface)",
"on-surface-variant": "var(--mcu-on-surface-variant)",

// Outline colors
outline: "var(--mcu-outline)",
"outline-variant": "var(--mcu-outline-variant)",

// Inverse colors
"inverse-surface": "var(--mcu-inverse-surface)",
"inverse-on-surface": "var(--mcu-inverse-on-surface)",

// Primary colors
primary: "var(--mcu-primary)",
"on-primary": "var(--mcu-on-primary)",
"primary-container": "var(--mcu-primary-container)",
"on-primary-container": "var(--mcu-on-primary-container)",
"primary-fixed": "var(--mcu-primary-fixed)",
"primary-fixed-dim": "var(--mcu-primary-fixed-dim)",
"on-primary-fixed": "var(--mcu-on-primary-fixed)",
"on-primary-fixed-variant": "var(--mcu-on-primary-fixed-variant)",
"inverse-primary": "var(--mcu-inverse-primary)",

// Secondary colors
secondary: "var(--mcu-secondary)",
"on-secondary": "var(--mcu-on-secondary)",
"secondary-container": "var(--mcu-secondary-container)",
"on-secondary-container": "var(--mcu-on-secondary-container)",
"secondary-fixed": "var(--mcu-secondary-fixed)",
"secondary-fixed-dim": "var(--mcu-secondary-fixed-dim)",
"on-secondary-fixed": "var(--mcu-on-secondary-fixed)",
"on-secondary-fixed-variant": "var(--mcu-on-secondary-fixed-variant)",

// Tertiary colors
tertiary: "var(--mcu-tertiary)",
"on-tertiary": "var(--mcu-on-tertiary)",
"tertiary-container": "var(--mcu-tertiary-container)",
"on-tertiary-container": "var(--mcu-on-tertiary-container)",
"tertiary-fixed": "var(--mcu-tertiary-fixed)",
"tertiary-fixed-dim": "var(--mcu-tertiary-fixed-dim)",
"on-tertiary-fixed": "var(--mcu-on-tertiary-fixed)",
"on-tertiary-fixed-variant": "var(--mcu-on-tertiary-fixed-variant)",

// Error colors
error: "var(--mcu-error)",
"on-error": "var(--mcu-on-error)",
"error-container": "var(--mcu-error-container)",
"on-error-container": "var(--mcu-on-error-container)",

// Other colors
scrim: "var(--mcu-scrim)",
shadow: "var(--mcu-shadow)",
};

// Shade mappings for primary, secondary, tertiary, error, neutral, and neutral-variant
const shadeColors = {};

const paletteColors = [
"primary",
"secondary",
"tertiary",
"error",
"neutral",
"neutral-variant",
];
const shades = {
50: 95,
100: 90,
200: 80,
300: 70,
400: 60,
500: 50,
600: 40,
700: 30,
800: 20,
900: 10,
950: 5,
};

paletteColors.forEach((palette) => {
Object.entries(shades).forEach(([shade, mcuValue]) => {
shadeColors[`${palette}-${shade}`] = `var(--mcu-${palette}-${mcuValue})`;
});
});

// Custom color mappings
const customColorMappings = {};

customColors.forEach((colorName) => {
// Convert camelCase to kebab-case for CSS variables
const kebabName = colorName
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
.toLowerCase();

// Base custom color mappings
customColorMappings[colorName] = `var(--mcu-${kebabName})`;
customColorMappings[`on-${colorName}`] = `var(--mcu-on-${kebabName})`;
customColorMappings[`${colorName}-container`] =
`var(--mcu-${kebabName}-container)`;
customColorMappings[`on-${colorName}-container`] =
`var(--mcu-on-${kebabName}-container)`;

// Shade mappings for custom colors
Object.entries(shades).forEach(([shade, mcuValue]) => {
customColorMappings[`${colorName}-${shade}`] =
`var(--mcu-${kebabName}-${mcuValue})`;
});
});

return {
theme: {
extend: {
colors: {
...baseColors,
...shadeColors,
...customColorMappings,
},
},
},
};
}
2 changes: 2 additions & 0 deletions tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ export default defineConfig({
onSuccess: async () => {
// Copy tailwind.css to dist
copyFileSync("src/tailwind.css", "dist/tailwind.css");
// Copy tailwind-plugin.js to dist
copyFileSync("src/tailwind-plugin.js", "dist/tailwind-plugin.js");
},
});