Tailwind CSSでcolor属性を取得

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

アイコンコンポーネントを作る時、propsで色に関する属性を取得してclassNameに追加したかった。

アイコンはSVGで構成されており、fillとstrokeの値を直接指定するのではなく、classNameにTailwind CSSのオートコンプリートを利用して色を指定したかった。

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

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

tailwindのオートコンプリートの力を借りるためにはfillと strokeのタイプにstringの代わりに他のタイプを入れる必要があります。 つまり、tailwindに設定されているcolor classesの名前を取得する必要があります。

タイプを抽出する

まず、tailwindの基本的なcolor情報を取得します。

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

const color: DefaultColors = 'blue'

Image.png

しかし、カラーキーだけが自動補完されるだけで、その後ろの属性は提供されません。(blueはできますが、blue-500などの自動補完はされません)

次のステップとして、tailwindのconfig全体を取得してみましょう。

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

const fullConfig = resolveConfig(tailwindConfig);

すると、fullConfigでは次のような情報を取得することができます。

Image.png

上記の情報を組み合わせてColorShadeという新しいタイプを作成してみましょう。

type ColorShade<T extends DefaultColors> = keyof ColorConfig[T] extends
  | string
  | number
  ? keyof ColorConfig[T]
  : neverconst shade: ColorShade<'blue'> = '500'

Image.png

これで色の後ろの属性も取得できるようになりました。

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

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

Image.png

適用

次は、私が欲しかった機能であるfillにはfillに入れるclassName、strokeにはstrokeだけ入れるclassNameを作りましょう。

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

Image.png

カスタムカラー適用

上のコードの問題点はtailwindの基本的な色だけ取ってきて、ユーザーが定義した色は取れないです。

カスタムカラーの分離

まず、カスタムで適用したcolorsを一つの変数で分離してみましょう。

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

そして上で使ってたDefaultColorsの代わりに下記のタイプを作りましょう。

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

最終コード

tailwin.config.ts

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

Component.tsx

const fullConfig = resolveConfig(tailwindConfig);
const colorTheme = fullConfig.theme.colors as Colorstype ColorConfig = typeof colorTheme;
type ColorKeys = keyof Colorstype ColorShade<T extends ColorKeys> = keyof ColorConfig[T] extends
  | string
  | number
  keyof ColorConfig[T] ?
  : nevertype TailwindColorClass = { {...
  [P in ColorKeys]:ColorShade<P> never extends ? P :`${P}-${ColorShade<P>}`;
}[ColorKeys];



interface IconProps {
  塗りつぶしを行います:`fill-${TailwindColorClass}`;
  ストローク:`storke-${TailwindColorClass}`;
}