从Tailwind CSS中提取颜色属性

profile image

让我们提取Tailwind CSS中设置的颜色类型!

本帖由 DeepL 翻译。如有任何翻译错误,请告知我们!

在创建图标组件时,我想通过props接收与颜色相关的属性,并将它们添加到className中。

图标由SVG组成,我想使用Tailwind CSS的自动完成功能在className中指定颜色,而不是直接指定fill和stroke值。

例如,我想编写这样的代码:

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的className和只能用于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