Installation
pnpm i class-variance-authority
Do 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\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
]
}
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));