Installation
pnpm i class-variance-authorityDo I really have to write such a long package name?
Unfortunately, for a little bit longer, yes. Originally, the plan was to publish the package as cva, but this name was taken and marked as a "placeholder" (opens in a new tab).
On 2022/02/16, GitHub transferred NPM ownership of cva to Joe Bell (opens in a new tab). This shorter name will be used from v1 onwards.
In the meantime, you can always alias the package for your convenience…
- 
Alias the package with npm install(opens in a new tab)npm i cva@npm:class-variance-authority
- 
Then import like so: import { cva } from "cva"; // …
Tailwind CSS
If you're a Tailwind user, here are some additional (optional) steps to get the most out of cva:
IntelliSense
You can enable autocompletion inside cva using the steps below:
- 
Install the "Tailwind CSS IntelliSense" Visual Studio Code extension (opens in a new tab) 
- 
Add the following to your settings.json(opens in a new tab):
{
  "tailwindCSS.experimental.classRegex": [
    ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
  ]
}Handling Style Conflicts
Although cva's API is designed to help you avoid styling conflicts, there's still a small margin of error.
If you're keen to lift that burden altogether, check out the wonderful tailwind-merge (opens in a new tab) package.
For bulletproof components, wrap your cva component with twMerge.
Example with tailwind-merge
import { cva, type VariantProps } from "class-variance-authority";
import { twMerge } from "tailwind-merge";
 
const buttonVariants = cva(["your", "base", "classes"], {
  variants: {
    intent: {
      primary: ["your", "primary", "classes"],
    },
  },
  defaultVariants: {
    intent: "primary",
  },
});
 
export interface ButtonVariants extends VariantProps<typeof buttonVariants> {}
 
export const button = (variants: ButtonVariants) =>
  twMerge(buttonVariants(variants));