I'm building a React component library with Tailwind CSS v4 and Rollup. When I publish the library and use it in another project, the Tailwind styles from my component variants don't apply, but custom className props work fine.
Button.tsx
import type { ButtonHTMLAttributes } from "react"
import { twMerge } from "tailwind-merge"
export interface IButton extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "base" | "primary" | "secondary"
}
const styles = {
base: "border border-gray-300 bg-transparent hover:border-gray-400",
primary: "bg-amber-500 border border-amber-500 text-white hover:border-amber-600 hover:bg-amber-600 disabled:bg-amber-500/50 disabled:border-amber-500/1",
secondary: "bg-gray-200 border border-gray-200 text-gray-800 hover:bg-gray-300 hover:border-gray-300 disabled:bg-gray-100 disabled:border-gray-100"
}
export const Button = ({ type = "submit", disabled = false, className, variant = "base", children }: IButton) => {
return (
<button type={type} disabled={disabled} className={twMerge(`rounded-md px-4 py-2 cursor-pointer disabled:cursor-not-allowed transition-colors duration-150 uppercase ${styles[variant]} ${className}`)}>
{children}
</button>
)
}
src/index.ts
import "./styles.css";
export * from "./components";
styles.css
@import "tailwindcss";
package.json:
{
"name": "react-ui-lib-npm",
"version": "1.0.0",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
"@rollup/plugin-typescript": "^11.0.0",
"@tailwindcss/postcss": "^4.0.0",
"@types/react": "^18.0.0",
"rollup": "^2.79.2",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-terser": "^7.0.2",
"tailwindcss": "^4.0.0",
"typescript": "^5.0.0"
},
"dependencies": {
"clsx": "^2.0.0",
"tailwind-merge": "^3.3.1",
"tslib": "^2.8.1"
}
}
rollup.config.js
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "@rollup/plugin-typescript";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
import { terser } from "rollup-plugin-terser";
export default {
input: "src/index.ts",
output: [
{
file: "dist/index.cjs.js",
format: "cjs",
sourcemap: true,
},
{
file: "dist/index.esm.js",
format: "esm",
sourcemap: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
postcss({
config: {
path: "./postcss.config.js",
},
extract: true,
minimize: true,
sourceMap: true,
extensions: [".css"],
}),
typescript({
tsconfig: "./tsconfig.json",
}),
terser(),
],
external: ["react", "react-dom"],
};
postcss.config.mjs
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
},
};
