Skip to content

What's New?

This content is for Beta. Switch to the latest version for up-to-date documentation.


What’s changed since class-variance-authority@0.*?

Roll your own cva via the new defineConfig API in cva/core.

Use cva/cx with tailwind-merge or a drop-in like cnfast via the cx option.

Shallow merge one or more cva components into a single component via the new composes property.

This replaces the compose function.

Extract a plain-object schema (variant names, values and defaults) from a cva component via the new getSchema utility. Use it to generate Storybook controls or any other UI that reads a component’s variants.

4. Bring your own concatenator with cva/core

Section titled “4. Bring your own concatenator with cva/core”

The cva package is now a preset over a lean core: importing from cva gives you cva/cx wired up with clsx, exactly like class-variance-authority. The new cva/core entry point exposes the same engine with no concatenator wired up, so you can swap in tailwind-merge, cnfast, clsx/lite, or your own function via the required cx option. The authoring surface adopts your concatenator’s input type automatically, so your variants are typechecked against exactly what it supports.

The compose method is deprecated in favor of the composes property inside cva. Pass a single component directly, or pass multiple components as an array.

import { cva, compose } from "cva";
import { cva } from "cva";
const box = cva({ /* ... */ });
const root = cva({ /* ... */ });
const card = compose(box, root);
const card = cva({ composes: [box, root] });

See Composing Components for more details and migration examples.

One of the biggest (and let’s be honest, most important) complaints about class-variance-authority was that the name was just too damn long.

Shout-out to GitHub for transferring npm ownership of cva!

Base styles are now applied via the named base property.

import { cva } from "class-variance-authority";
import { cva } from "cva";
const component = cva({ base: "your-base-class" });

Previously, passing null to a variant would disable it completely, to match the behavior of Stitches.js. However, this caused a great deal of confusion.

Instead, we now recommend explicitly rolling your own unset variant.

cva uses generic type parameters to infer variant types. Some users mistook these for a customization option.

If you now pass a generic type parameter, cva throws an error.