Documentation
Getting Started
Polymorphism

Polymorphism

cva components are polymorphic (and framework-agnostic) by default; just apply the class to your preferred HTML element…

import { button } from "./components/button";
 
export default () => (
  <a className={button()} href="/sign-up">
    Sign up
  </a>
);

Alternative Approaches

React

If you'd prefer to use a React-based API, cva strongly recommends using @radix-ui's Slot component (opens in a new tab) to create your own asChild prop.

// ./components/button.tsx
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
 
const button = cva("button", {
  variants: {
    intent: {
      primary: [
        "bg-blue-500 text-white",
        "text-white",
        "border-transparent",
        "hover:bg-blue-600",
      ],
      secondary: [
        "bg-white",
        "text-gray-800",
        "border-gray-400",
        "hover:bg-gray-100",
      ],
    },
  },
  defaultVariants: {
    intent: "primary",
  },
});
 
export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof button> {
  asChild?: boolean;
}
 
export const Button: React.FC<ButtonProps> = ({
  asChild,
  className,
  intent,
  ...props
}) => {
  const Comp = asChild ? Slot : "button";
 
  return <Comp className={button({ intent, className })} {...props} />;
};

Usage

import { Button } from "./components/button";
 
// Renders:
//   <a href="/sign-up" class="bg-blue-500 text-white text-white border-transparent hover:bg-blue-600">
//     Sign up
//   </a>
export default () => (
  <Button asChild>
    <a href="/sign-up">Sign up</a>
  </Button>
);