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 to create your own asChild
prop.
import * as React from "react";import { Slot } from "@radix-ui/react-slot";import { cva, type VariantProps } from "cva";
const button = cva({ base: "button", variants: { intent: { primary: "bg-blue-500 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 border-transparent hover:bg-blue-600">// Sign up// </a>export default () => ( <Button asChild> <a href="/sign-up">Sign up</a> </Button>);