在创建图标组件时,我想通过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的自动完成功能,我需要为fill
和stroke
类型使用string
以外的类型。换句话说,我需要提取Tailwind中配置的颜色类的名称。
提取类型
首先,我们可以从Tailwind获取基本的颜色信息。
typescript
import defaultColors from "tailwindcss/colors";
export type DefaultColors = keyof typeof defaultColors;
const color: DefaultColors = 'blue'
然而,只有颜色键会自动完成,而不是后面的属性。(blue
可以工作,但blue-500
等不会自动完成)
接下来,让我们获取整个Tailwind配置。
typescript
import resolveConfig from "tailwindcss/resolveConfig";
import tailwindConfig from "web/tailwind.config.ts"; // Tailwind配置文件
const fullConfig = resolveConfig(tailwindConfig);
然后我们可以从fullConfig
获取以下信息:
让我们结合上述信息创建一个名为ColorShade
的新类型
typescript
type ColorShade<T extends DefaultColors> = keyof ColorConfig[T] extends
| string
| number
? keyof ColorConfig[T]
: never;
const shade: ColorShade<'blue'> = '500'
现在我们也可以获取颜色后面的属性。
通过组合这些,我们可以提取结合颜色和亮度的名称。
typescript
type TailwindColorClass = {
[P in DefaultColors]: ColorShade<P> extends never ? P : `${P}-${ColorShade<P>}`;
}[DefaultColors];
应用
现在让我们创建可以用于fill的className和只能用于stroke的className,这是我想要的功能。
typescript
interface IconProps {
fill: `fill-${TailwindColorClass}`;
stroke: `storke-${TailwindColorClass}`;
}
应用自定义颜色
上述代码的问题是它只获取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}`;
}