React
Variants

Adding Variants

You can add variants using the variants key. There is no limit to the amount of variants you can add.

const Button = classed("button", {
  variants: {
    color: {
      primary: "text-white bg-blue-500",
      secondary: "text-white bg-gray-700",
    },
  },
});
 
() => <Button color="primary">Button</Button>;

A variant accepts a single string of tailwind class names.

Multiple variants

const Button = classed("button", {
  variants: {
    color: {
      primary: "text-white bg-blue-500",
      secondary: "text-white bg-gray-700",
    },
    size: {
      small: "py-2 px-4",
      medium: "py-3 px-6",
      large: "py-4 px-8",
    },
  },
});
 
() => (
  <Button color="primary" size="medium">
    Button
  </Button>
);

Boolean variants

Variants can be booleans by using true as the key.

const Button = classed("button", {
  variants: {
    // ... base variants
    outlined: {
      true: "border border-gray-600",
    },
  },
});
 
() => (
  <Button color="primary" size="medium" outlined>
    Button
  </Button>
);

Default variants

You can use the defaultVariants key to set a variant by default:

const Button = classed("button", {
  variants: {
    color: {
      primary: "text-white bg-blue-500",
      secondary: "text-white bg-gray-700",
    },
  },
  defaultVariants: {
    color: "primary",
  },
});
 
() => <Button>Button</Button>;

Compound variants

Compound variants are variants that depend on other variants. They are defined using an array of variants and a class/className

You can use the compoundVariants key to create compound variants:

const Button = classed("button", {
  variants: {
    color: {
      primary: "text-white bg-blue-500",
      secondary: "text-white bg-gray-700",
    },
    size: {
      small: "py-2 px-4",
      medium: "py-3 px-6",
      large: "py-4 px-8",
    },
  },
  compoundVariants: [
    {
      size: "small",
      color: "primary",
      class: "rounded", // Classes when both size and color are small and primary will be applied
      className: "", // This is also supported if you prefer to use className
    },
  ],
});
 
() => (
  <Button color="primary" size="medium">
    Button
  </Button>
);

Extracting variants

You can extract variants from a component using the getVariantConfig() function. This is useful if you want to manually compose comonents or show variants in docs/Storybook.

import { classed, getVariantConfig } from "@tw-classed/react";
 
const Button = classed.button({
  variants: {
    color: {
      primary: "text-white bg-blue-500",
      secondary: "text-white bg-gray-700",
    },
    size: {
      small: "py-2 px-4",
      medium: "py-3 px-6",
      large: "py-4 px-8",
    },
  },
});
 
const buttonConfig = getVariantConfig(Button);
 
assert.equals(buttonConfig.variants, {
  color: {
    primary: "text-white bg-blue-500",
    secondary: "text-white bg-gray-700",
  },
  size: {
    small: "py-2 px-4",
    medium: "py-3 px-6",
    large: "py-4 px-8",
  },
});

Usage in Storybook

Here we are assuming that you have a utility function to convert the variant config into a Storybook argTypes object.

const meta = {
  argTypes: {
    ...variantArgTypes(getVariantConfig(Button)),
  },
  component: Button,
} satisfies Meta<typeof Button>;
 
export default meta;