> ## Documentation Index
> Fetch the complete documentation index at: https://joe-bell-cva-85.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Extending Components

> Override variants on an existing CVA component, create specialized variants using VariantProps, and combine components with compose.

# Extending components

CVA provides several ways to extend or build on top of existing components: ad-hoc class overrides via the `class` prop, specialized components that share a base variant definition, and the `compose` helper for merging two CVA components into one.

## Ad-hoc overrides with the `class` prop

Every CVA component accepts an optional `class` **or** `className` prop. Classes passed here are appended after all resolved variant classes, making them the simplest way to add one-off styles:

```typescript components/button.ts theme={null}
import { cva } from "class-variance-authority";

const button = cva(/* … */);

button({ class: "m-4" });
// => "…buttonClasses m-4"

button({ className: "m-4" });
// => "…buttonClasses m-4"
```

> [!NOTE]
>
> `class` and `className` are mutually exclusive. Passing both at once is a TypeScript error.

For style conflict resolution when overriding Tailwind classes, see the [Tailwind CSS guide](https://joe-bell-cva-85.mintlify.site/guides/tailwind-css.md).

## Creating a specialized variant

When you want a component that always sets a specific variant value — for example, a `PrimaryButton` that is always `intent: "primary"` — extract the variant props with `VariantProps` and re-use the same `cva` definition:

```typescript components/button.ts theme={null}
import { cva, type VariantProps } from "class-variance-authority";

export const button = cva(["font-semibold", "border", "rounded"], {
  variants: {
    intent: {
      primary: ["bg-blue-500", "text-white", "border-transparent"],
      secondary: ["bg-white", "text-gray-800", "border-gray-400"],
    },
    size: {
      small: ["text-sm", "py-1", "px-2"],
      medium: ["text-base", "py-2", "px-4"],
    },
  },
  defaultVariants: {
    intent: "primary",
    size: "medium",
  },
});

export type ButtonProps = VariantProps<typeof button>;

// A specialized variant that locks in the intent
export type PrimaryButtonProps = Omit<ButtonProps, "intent">;
export const primaryButton = (props: PrimaryButtonProps) =>
  button({ ...props, intent: "primary" });
```

`VariantProps` infers the full set of variant props from the `cva` definition, giving you a type-safe foundation to build on.

## Composing two CVA components with `compose`

The `compose` helper (available in the `cva` package) merges two or more CVA components into a single callable. The returned function accepts the union of all variant props and resolves each component's classes:

```typescript components/card.ts theme={null}
import { cva, compose } from "cva";
import 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 cardBase = cva({
  base: ["card", "border-solid", "border-slate-300", "rounded"],
  variants: {
    shadow: {
      md: "drop-shadow-md",
      lg: "drop-shadow-lg",
      xl: "drop-shadow-xl",
    },
  },
});

export const card = compose(box, cardBase);
export type CardProps = VariantProps<typeof card>;

card({ margin: 4, padding: 2, shadow: "md" });
// => "box box-border m-4 p-2 card border-solid border-slate-300 rounded drop-shadow-md"
```

The `card` function accepts `margin`, `padding`, and `shadow` as a single flat props object. `compose` distributes the props to each component internally.

> [!NOTE]
>
> `compose` is exported from the `cva` package (v1+). It is not available in the legacy `class-variance-authority` package.

## Choosing an approach

> **class prop**
>
> One-off overrides at the call site. No new abstraction needed.

> **VariantProps specialization**
>
> Lock in one or more variants. Keeps the base definition as the source of truth.

> **compose**
>
> Merge independent variant sets into one component. Requires `cva` v1+.

For the `cx`-based manual composition approach, see [Composing components](https://joe-bell-cva-85.mintlify.site/getting-started/composing-components.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.