tailwindの色指定をCSS変数でやる
前提
この場合、外部から色を受け取る方法がCSS変数しかない
アプローチ
tailwindcss/resolveConfigを使うと現在適用されているコンフィグが取れるので、そこから色を取り出してCSS変数に入れるようなコードを書く
やる
型書く
code:tailwind.d.ts
declare module "tailwindcss/resolveConfig" {
export interface Config {
theme: {
colors: Colors;
};
}
function resolveConfig(): Config;
export default resolveConfig;
}
ジェネレータを書く
code:generate-colors.ts
import fs from "fs";
import resolveConfig, { Colors } from "tailwindcss/resolveConfig";
function flattenColors(colors: Colors): Record<string, string> {
return Object.entries(c).flatMap((key, val) => { if (typeof val === "string") {
return key, val;
} else {
const r = go(val).map(
);
return r;
}
});
}
return Object.fromEntries(go(colors));
}
const config = resolveConfig();
const colors = flattenColors(config.theme.colors);
const json = JSON.stringify(colors, null, 2);
const source = `
// DO NOT EDIT THIS FILE
const colors = ${json};
export type Colors = keyof typeof colors;
export default colors;
`;
fs.writeFileSync("src/themes/colors.ts", source, "utf8");
生成された色情報を利用するhookを書く
code:useThemeColor.ts
import { useMemo } from "react";
import colors, { Colors } from "themes/colors";
export function useThemeColor(
...vars: readonly [variable: --${string}, color: Colors][]
): React.CSSProperties {
const deps = vars.flat();
const style = useMemo((): React.CSSProperties => {
const style: React.CSSProperties = {};
}
return style;
}, deps);
return style;
}
code:Hoge.tsx
import type { Colors } from "theme/colors";
import styles from "./Hoge.module.css";
const Hoge: React.VFC<{ color?: Colors }> = ({ color = "blue-500" }) => {
return <div className={styles.hoge} style={style} />
}
code:Hoge.module.css
.hoge {
@apply container;
background-color: var(--color);
}
みたいな感じで使う