Tailwind CSSからカラープロパティを取得する

profile image

Tailwind CSSで設定されたカラータイプを取得してみましょう!

この記事は DeepL によって翻訳されました。誤訳があれば教えてください!

アイコンコンポーネントを作成する際、色に関連するプロパティをpropsとして受け取り、classNameに追加したいと思いました。

アイコンはSVGで構成されており、fillとstrokeの値を直接指定する代わりに、Tailwind CSSの自動補完を活用してclassNameで色を指定したいと思いました。

例えば、次のようなコードを書きたいと思いました:

typescript
interface IconProps {
  fill: string;
  stroke: string;
}
const Icon = ({fill, stroke}: IconProps) => {
  <svg className={`${fill} ${stroke} `} />
}

Tailwindの自動補完を活用するには、fillstrokeの型にstringではなく別の型を使用する必要がありました。つまり、Tailwindに設定されている色クラスの名前を取得する必要があります。

型の抽出

まず、Tailwindの基本的な色情報を取得できます。

typescript
import defaultColors from "tailwindcss/colors";
export type DefaultColors = keyof typeof defaultColors;

const color: DefaultColors = 'blue'

Image.png

しかし、カラーキーのみが自動補完され、その後のプロパティは提供されません。(blueは機能しますが、blue-500などは自動補完されません)

次のステップとして、Tailwindの全体的な設定を取得しましょう。

typescript
import resolveConfig from "tailwindcss/resolveConfig";
import tailwindConfig from "web/tailwind.config.ts"; // Tailwind設定ファイル

const fullConfig = resolveConfig(tailwindConfig);

するとfullConfigから次のような情報を取得できます:

Image.png

上記の情報を組み合わせて、ColorShadeという新しい型を作成してみましょう

typescript
type ColorShade<T extends DefaultColors> = keyof ColorConfig[T] extends
  | string
  | number
  ? keyof ColorConfig[T]
  : never;

const shade: ColorShade<'blue'> = '500'

Image.png

これで色の後のプロパティも取得できるようになりました。

これらを組み合わせることで、色と明るさを組み合わせた名前を抽出できるようになりました。

typescript
type TailwindColorClass = {
  [P in DefaultColors]: ColorShade<P> extends never ? P : `${P}-${ColorShade<P>}`;
}[DefaultColors];

Image.png

適用

これで私が望んでいた機能である、fillにはfillに入れることができるclassName、strokeにはstrokeにのみ入れることができるclassNameを作成しましょう。

typescript
interface IconProps {
  fill: `fill-${TailwindColorClass}`;
  stroke: `storke-${TailwindColorClass}`;
}

Image.png

カスタムカラーの適用

上記のコードの問題点は、Tailwindのデフォルトカラーのみを取得し、ユーザーが定義したカラーは取得できないことです。

カスタムカラーの分離

まず、カスタムで適用されたカラーを一つの変数に分離しましょう。

typescript
const color = {
  ...formalColors,
  ...keyColors,
  ...accentColors,
  ...grayColor,
  ...theme.colors,
}

そして、上記で使用したDefaultColorsの代わりに以下の型を作成しましょう

typescript
type CustomColors = typeof color;
type DefaultColors = typeof defaultColors;
export type Colors = CustomColors & DefaultColors;

最終コード

tailwin.config.ts

typescript
type CustomColors = typeof color;
export type DefaultColors = typeof defaultColors;
export type Colors = CustomColors & DefaultColors;

Component.tsx

typescript
const fullConfig = resolveConfig(tailwindConfig);
const colorTheme = fullConfig.theme.colors as Colors;
type ColorConfig = typeof colorTheme;
type ColorKeys = keyof Colors;

type ColorShade<T extends ColorKeys> = keyof ColorConfig[T] extends
  | string
  | number
  ? keyof ColorConfig[T]
  : never;


type TailwindColorClass = {
  [P in ColorKeys]: ColorShade<P> extends never ? P : `${P}-${ColorShade<P>}`;
}[ColorKeys];



interface IconProps {
  fill: `fill-${TailwindColorClass}`;
  stroke: `storke-${TailwindColorClass}`;
}
❤️ 0
🔥 0
😎 0
⭐️ 0
🆒 0