Composing Components
This content is for Beta. Switch to the latest version for up-to-date documentation.
Shallow merge one or more cva components into a single component with the composes property. Pass a single component directly, or pass multiple components as an array:
import { cva, type VariantProps } from "cva";
const box = cva({ base: "box box-border", variants: { margin: { 0: "m-0", 2: "m-2", 4: "m-4", 8: "m-8" }, padding: { 0: "p-0", 2: "p-2", 4: "p-4", 8: "p-8" }, }, defaultVariants: { margin: 0, padding: 0, },});
const root = cva({ base: "card rounded border-solid border-slate-300", variants: { shadow: { md: "drop-shadow-md", lg: "drop-shadow-lg", xl: "drop-shadow-xl", }, },});
export const card = cva({ composes: [box, root] });export interface CardProps extends VariantProps<typeof card> {}
card({ margin: 2, shadow: "md" });// => "box box-border m-2 p-0 card rounded border-solid border-slate-300 drop-shadow-md"card({ margin: 2, shadow: "md", class: "adhoc-class" });// => "box box-border m-2 p-0 card rounded border-solid border-slate-300 drop-shadow-md adhoc-class"Extending variants
Section titled “Extending variants”If more than one composed component declares the same variant, their values combine. Each component still resolves and applies its own class, so overlapping values extend one another rather than override:
const a = cva({ base: "a", variants: { style: { primary: "a-primary" } } });const b = cva({ base: "b", variants: { style: { primary: "b-primary", secondary: "b-secondary" } },});
const combined = cva({ composes: [a, b] });
combined({ style: "primary" });// => "a a-primary b b-primary"defaultVariants follow a last-wins merge. If multiple composed components declare a default for the same variant, the last one in the array wins. A local defaultVariants on the composing component wins over all of them. cva applies that value to every composed component, not just the one that declared it:
const a = cva({ base: "a", variants: { style: { primary: "a-primary" } }, defaultVariants: { style: "primary" },});const b = cva({ base: "b", variants: { style: { primary: "b-primary", secondary: "b-secondary" } }, defaultVariants: { style: "secondary" },});
const combined = cva({ composes: [a, b] });
combined();// => "a b b-secondary"