Typescript
Tailwind Variants provides typing out of the box, but this page contains some further utilities and tips.
Extract variants from a component
You can use the VariantProps
utility to extract variants from a component.
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'
}
]
});
/**
* Result:
* 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>;
};
Required variants
Tailwind Variants doesn't offer a way to make variants required yet, but you can use TypeScript's Utility Types (opens in a new tab) to achieve this.
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: [...],
});
/**
* Result:
* 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 Error:
// 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 });
This sample is taken from the "Required Variants" section of the CVA (opens in a new tab) project on Github, which was developed by Joe Bell (opens in a new tab).