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: "font-semibold border rounded",
// **or**
// base: ["font-semibold", "border", "rounded"],
variants: {
intent: {
primary: "bg-blue-500 text-white border-transparent hover:bg-blue-600",
// **or**
// primary: [
// "bg-blue-500",
// "text-white",
// "border-transparent",
// "hover:bg-blue-600",
// ],
secondary: "bg-white text-gray-800 border-gray-400 hover:bg-gray-100",
},
size: {
small: "text-sm py-1 px-2",
medium: "text-base py-2 px-4",
},
},
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"