From 453f8335feabffba675d61a149db7c316767f85f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:13:44 +0000 Subject: [PATCH 1/4] Initial plan From e551a0b61823e6225027a56a6612564f5af753be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:19:47 +0000 Subject: [PATCH 2/4] Add Tailwind 4 plugin with custom colors support and type definitions Co-authored-by: abernier <76580+abernier@users.noreply.github.com> --- README.md | 29 ++++++++ package.json | 12 ++- scripts/post-build.js | 5 ++ src/tailwind-plugin.d.ts | 39 ++++++++++ src/tailwind-plugin.js | 157 +++++++++++++++++++++++++++++++++++++++ tsup.config.ts | 2 + 6 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 scripts/post-build.js create mode 100644 src/tailwind-plugin.d.ts create mode 100644 src/tailwind-plugin.js diff --git a/README.md b/README.md index 8f37ee5..8d31c99 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/package.json b/package.json index e3cd4d3..7e05f28 100644 --- a/package.json +++ b/package.json @@ -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": { @@ -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", @@ -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", diff --git a/scripts/post-build.js b/scripts/post-build.js new file mode 100644 index 0000000..3c35cfd --- /dev/null +++ b/scripts/post-build.js @@ -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/"); diff --git a/src/tailwind-plugin.d.ts b/src/tailwind-plugin.d.ts new file mode 100644 index 0000000..8d7234e --- /dev/null +++ b/src/tailwind-plugin.d.ts @@ -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; + }; + }; +}; diff --git a/src/tailwind-plugin.js b/src/tailwind-plugin.js new file mode 100644 index 0000000..8a49246 --- /dev/null +++ b/src/tailwind-plugin.js @@ -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, + }, + }, + }, + }; +} diff --git a/tsup.config.ts b/tsup.config.ts index b009eaa..0825fce 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -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"); }, }); From 5acf19ff2f3796f75954ad32eb0c2b729ceef322 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:20:48 +0000 Subject: [PATCH 3/4] Add example CSS file demonstrating plugin usage Co-authored-by: abernier <76580+abernier@users.noreply.github.com> --- examples/tailwind-plugin-usage.css | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 examples/tailwind-plugin-usage.css diff --git a/examples/tailwind-plugin-usage.css b/examples/tailwind-plugin-usage.css new file mode 100644 index 0000000..6e2ec61 --- /dev/null +++ b/examples/tailwind-plugin-usage.css @@ -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. + */ From 4b71284d60711afb910b7fe155b5eef19e6906ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:22:55 +0000 Subject: [PATCH 4/4] Fix customColors property name in README example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d31c99..99b3aec 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ If you're using custom colors, pass them to the plugin: ```css @import "tailwindcss"; @plugin "react-mcu/tailwind-plugin" { - customcolors: + customColors: [ "myCustomColor1", "myCustomColor2", "myCustomColor3"];