Lzh on GitHub

Tailwind Variants 开箱即用地提供了类型支持,但本页面包含了一些进一步的实用工具和技巧。

从组件中提取变体

您可以使用 VariantProps 工具来从组件中提取变体。

import { tv, type VariantProps } from 'tailwind-variants';
 
export const button = tv({
  base: 'px-4 py-1.5 rounded-full hover:opacity-80',
  variants: {
    color: {
      primary: 'bg-blue-500 text-white',
      neutral: 'bg-zinc-500 text-black dark:text-white'
    },
    flat: {
      true: 'bg-transparent'
    }
  },
  defaultVariants: {
    color: 'primary'
  },
  compoundVariants: [
    {
      color: 'primary',
      flat: true,
      class: 'bg-blue-500/40'
    },
    {
      color: 'neutral',
      flat: true,
      class: 'bg-zinc-500/20'
    }
  ]
});
 
/**
 * 结果:
 * color?: "primary" | "neutral"
 * flat?: boolean
 */
type ButtonVariants = VariantProps<typeof button>;
 
interface ButtonProps extends ButtonVariants {
  children: React.ReactNode;
}
 
export const Button = (props: ButtonProps) => {
  return <button className={button(props)}>{props.children}</button>;
};

必填变体

Tailwind Variants 尚不提供将变体设为必填的方法,但您可以使用 TypeScript 的 工具类型(Utility Types) 来实现。

import { tv, type VariantProps } from 'tailwind-variants'
 
const buttonStyles = tv({
  base: "px-4 py-1.5 rounded-full hover:opacity-80",
  variants: {
    color: {
      primary: "bg-blue-500 text-white",
      neutral: "bg-zinc-500 text-black dark:text-white",
    },
    requiredFlat: {
      true: "bg-transparent",
      false: "bg-white",
    },
  },
  defaultVariants: {
    color: "primary",
  },
  compoundVariants: [...],
});
 
/**
 * 结果:
 * color?: "primary" | "neutral"
 * flat?: boolean
 */
type ButtonVariants = VariantProps<typeof buttonStyles>
 
export interface ButtonProps
  extends Omit<ButtonVariants, "requiredFlat">,
    Required<Pick<ButtonVariants, "requiredFlat">> {}
 
export const button = (props: ButtonProps) => buttonStyles(props);
 
// ❌ TypeScript 错误:
// Argument of type "{}": is not assignable to parameter of type "ButtonProps".
// Property "requiredFlat" is missing in type "{}" but required in type "ButtonProps".
button({});
 
// ✅
button({ requiredFlat: true });
此示例摘自 CVA 项目在 Github 上的 “必填变体” 部分,该项目由 Joe Bell 开发。