API Reference
This content is for Beta. Switch to the latest version for up-to-date documentation.
Builds a cva component
import { cva } from "cva";
const component = cva(options);A call reads only the props you pass it, plus the cx you gave defineConfig, which stays live. Getters with side effects, and changing the props object while the call is running, are unsupported.
Parameters
Section titled “Parameters”optionsbase: the base class name (string,string[]or otherclsxvalue)variants: your variants schemacompoundVariants: variants based on a combination of previously defined variantsdefaultVariants: set default values for previously defined variantscomposes: shallow merge one or more othercvacomponents into this one, as a single component or an array (see Composing Components)
Returns
Section titled “Returns”A cva component function
Concatenates class names (an alias of clsx; swap in your own concatenator via cva/config).
import { cx } from "cva";
cx("button", "rounded");See the clsx documentation for examples of strings, arrays, and conditional objects. If you configure a different concatenator, follow its documentation for supported inputs; see handling class conflicts for the Tailwind CSS options.
Parameters
Section titled “Parameters”- Zero or more class values. The preset accepts
clsxvalues;cva/configuses the configured concatenator’s grammar
Returns
Section titled “Returns”string
cva/tailwindcss
Section titled “cva/tailwindcss”Custom Tailwind CSS variants, for use with or without cva. Import it after Tailwind CSS to add the base: variant.
Marks a utility as a component default. Ordinary utilities override base: utilities through the CSS cascade, and base: utilities still override browser defaults and Tailwind’s base and components layers.
See cva/tailwindcss for setup and limitations.
cva/tools
Section titled “cva/tools”getSchema
Section titled “getSchema”Extracts a plain-object schema (variant names, possible values, and default values) from a cva component. Use it to generate Storybook controls, documentation, or any other UI that reads a component’s variants without re-declaring them. See Tools for use cases.
import { cva } from "cva";import { getSchema } from "cva/tools";
const button = cva({ base: "button", variants: { intent: { primary: "button--primary", secondary: "button--secondary" }, disabled: { true: "button--disabled", false: "button--enabled" }, }, defaultVariants: { intent: "primary", disabled: false },});
getSchema(button);// => {// intent: { values: ["primary", "secondary"], defaultValue: "primary" },// disabled: { values: [true, false], defaultValue: false },// }getSchema omits internal variants or variants that have no values (e.g. variants: { empty: {} }).
Parameters
Section titled “Parameters”component: a component created by cva (including components composed via composes)
Returns
Section titled “Returns”An object keyed by variant name. Each entry has:
values: a readonly array of the variant’s possible valuesdefaultValue: present only if the variant has adefaultVariantsentry
cva/config
Section titled “cva/config”The cva package is a preset: cva and cx use clsx. cva/config is the same engine without a configured concatenator.
defineConfig
Section titled “defineConfig”Generate cva and cx functions based on your preferred configuration.
Store in a cva.config.ts file, and import across your project.
import { defineConfig } from "cva/config";
export const { cva, cx } = defineConfig(options);optionscx(required): the class name concatenator used bycvaandcx- It owns the class name grammar:
cvapasses composed outputs,base, matched variant and compound-variant values, andclass/classNamethrough verbatim, one argument each. - Custom callbacks must accept empty calls, variadic inputs, and composed component strings.
- The authoring surface adopts its parameter type:
twMergerejects object syntax, whileclsxkeeps the full clsx-flavoredClassValuegrammar. - See Handling class conflicts for CSS defaults,
cn, andtailwind-mergeexamples.
- It owns the class name grammar:
Advanced concatenators
Section titled “Advanced concatenators”Use clsx/lite only when every authored value is a string and you do not need conflict resolution. Its runtime ignores arrays, objects, and numbers even though its published types accept them. Annotate a string-only wrapper so cva rejects those values too:
import { defineConfig } from "cva/config";import { clsx as clsxLite } from "clsx/lite";
export const { cva, cx } = defineConfig({ cx: (...inputs: string[]) => clsxLite(...inputs),});