Typescript

UnoCSS 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.

types.ts
import type { VariantProps } from 'unocss-variants';
import { uv } from 'unocss-variants';

const button = uv({
  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
 */

export type ButtonVariants = VariantProps<typeof button>;

Required variants

UnoCSS Variants doesn't offer a way to make variants required yet, but you can use TypeScript's Utility Types to achieve this.

types.ts
import type { VariantProps } from 'unocss-variants';
import { tv } from 'unocss-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 project on Github, which was developed by Joe Bell.