Skip to main content

Using CVA in Next.js

The future state of component/application level styling will no longer rely on CSS/SCSS files (other than the necessary CSS files that store Tailwind configuration and drive theming). Tailwind will be used in tandem with CVA (Class Variance Authority) to easily map style options to the respective Tailwind classes.

CVA Intro/Overview

CVA (Class Variance Authority) is a JavaScript based, framework agnostic, variant management library. With CVA you can configure a few options that allow for variability across your component or HTML elements. The reserved property keywords CVA uses are variants, compoundVariants, and defaultVariants.

  • variants - base set of variations used by CVA to match a set of classes based on options passed
  • defaultVariants - the default settings to target from the variants object
  • compoundVariants - if needed, CVA allows you to define objects with properties to run checks on - if the properties are matched on the provided class will be applied as well.

Based on the options provided, a string will be then be returned with the correct styles pulled based on those passed settings.

The cva function accepts two arguments:

  1. An array of static classes to always apply to the element using this CVA mapping.
  2. The configuration object containing variants, etc.

Below is an example configuration and walk through of some examples of the output class string and the reasons behind that final output.

Example ConfigurationUsage Examples

The cva function accepts the two arguments of static classes always set regardless of options passed; a function is then returned that will then let you pass options to it to run the matching logic.

import { cva } from 'class-variance-authority';

const classMap = cva(['border-4'], {
variants: {
palette: {
black: ['bg-black', 'text-white'],
green: ['bg-green-200', 'text-black']
},
borderColor: {
red: ['border-red-400'],
green: ['border-green-200'],
blue: ['border-blue-300']
}
},
compoundVariants: [
{
palette: "black",
borderColor: "green",
class: "text-xl"
}
],
defaultVariants: {
palette: "black",
borderColor: "red"
}
});

// Now usable as the function that
// generates your classes:
const classes = classMap();
const classes2 = classMap({ palette: "green" });

No options passed

// Output: "border-4 bg-black text-white border-red-400"
const classes = classMap();
  • We have a default style of border-4 in the static class array. This class is always applied.
  • Since no options were passed for variants, the defaultVariants take over and cva pulls the class specified on black in the palette options in variants.
    • "bg-black text-white" classes are applied
  • Likewise, since no options were passed for variants, the default red option is used to pull the class "border-red-400" from borderColor in variants.

One option passed, other variant default

// Output: "border-4 bg-green-200 text-black border-red-400"
const classes = classMap({ palette: "green" });
  • Since we have a default style of "border-4" in the static class array, this will always be applied.
  • Since we supplied a palette option of green, CVA pulls the "bg-green-200 text-black" classes from variants.
  • As in Example 1, the default borderColor then kicks in, using the value of "red" to pull the "border-red-400" class from variants.

Both options passed

// Output: "border-4 bg-green-200 text-black border-blue-300"
const classes = classMap({ palette: "green", borderColor: "blue" });
  • Since we have a default style of border-4 in the static class array, this will always be applied.
  • Since we supplied a palette option of green, CVA pulls the "bg-green-200 text-black" classes from variants.
  • Since we passed a border color option of blue, CVA pulls the "border-blue-300".

Both options passed and match was found on compoundVariants

// Output: "border-4 bg-black text-white border-green-200 text-xl"
const classes = classMap({ palette: "black", borderColor: "green" });
  • Since we have a default style of "border-4" in the static class array, this will always be applied.
  • Since we supplied a palette option of black, CVA pulls the "bg-black text-white" classes from variants.
  • Since we passed a border color option of green, CVA pulls the "border-green-300" class.
  • Since we have an option in compoundVariants that has a condition of when palette is black and borderColor is green and this condition has been met with the options we passed, we also receive the "text-xl" class.

Using CVA in the NextJS App

TODO