Skip to content

Variants

Creating Variants

To kick things off, let’s build a “basic” button component, using cva to handle our variant’s classes

components/button.ts
import { cva } from "cva";
const button = cva({
base: "rounded border font-semibold",
// **or**
// base: ["font-semibold", "border", "rounded"],
variants: {
intent: {
primary: "border-transparent bg-blue-500 text-white hover:bg-blue-600",
// **or**
// primary: [
// "bg-blue-500",
// "text-white",
// "border-transparent",
// "hover:bg-blue-600",
// ],
secondary: "border-gray-400 bg-white text-gray-800 hover:bg-gray-100",
},
size: {
small: "px-2 py-1 text-sm",
medium: "px-4 py-2 text-base",
},
},
compoundVariants: [
{
intent: "primary",
size: "medium",
class: "uppercase",
// **or** if you're a React.js user, `className` may feel more consistent:
// className: "uppercase"
},
],
defaultVariants: {
intent: "primary",
size: "medium",
},
});
button();
// => "font-semibold border rounded bg-blue-500 text-white border-transparent hover:bg-blue-600 text-base py-2 px-4 uppercase"
button({ intent: "secondary", size: "small" });
// => "font-semibold border rounded bg-white text-gray-800 border-gray-400 hover:bg-gray-100 text-sm py-1 px-2"

Compound Variants

Variants that apply when multiple other variant conditions are met.

components/button.ts
import { cva } from "cva";
const button = cva({
base: "",
variants: {
intent: { primary: "", secondary: "" },
size: { small: "", medium: "" },
},
compoundVariants: [
// Applied via:
// `button({ intent: "primary", size: "medium" })`
{
intent: "primary",
size: "medium",
class: "",
},
],
});

Targeting Multiple Variant Conditions

components/button.ts
import { cva } from "cva";
const button = cva({
base: "",
variants: {
intent: { primary: "", secondary: "" },
size: { small: "", medium: "" },
},
compoundVariants: [
// Applied via:
// `button({ intent: "primary", size: "medium" })`
// or
// `button({ intent: "secondary", size: "medium" })`
{
intent: ["primary", "secondary"],
size: "medium",
class: "",
},
],
});

Disabling Variants

Want to disable a variant completely? Provide an option with a value of null.

If you’re stuck on naming, we recommend setting an explicit "unset" option (similar to the CSS keyword).

import { cva } from "cva";
const button = cva({
base: "button",
variants: {
intent: {
unset: null,
primary: "button--primary",
secondary: "button--secondary",
},
},
});
button({ intent: "unset" });
// => "button"