class-variance-authority (cva) 사용법 간단 정리

2024. 7. 2.

cva란?

cva는 class-variance-authority 라이브러리의 함수로, 조건부로 CSS 클래스 이름을 생성하고, 일관성 있는 UI 정의와 관리를 하기 위해 사용된다.

이 라이브러리는 다양한 변형(variants)을 정의하고, 이러한 변형을 기반으로 동적으로 클래스 이름을 생성할 수 있게 한다.

이를 통해 CSS 클래스 이름을 조합하고 조건부로 적용하는 작업을 간편하게 처리할 수 있다!

 

cva(baseStyle, {option}) 함수

먼저 코드를 보면 

cva 함수를 사용해서 컴포넌트에서 사용할 스타일을 만든다 (보통 이름은 "사용할 컴포넌트Variant")

 

첫번째 인자에는 공통적으로 사용될 스타일

두번째 인자에는 옵션 객체를 넣으면 된다

const buttonVariant = cva("rounded border font-semibold hover:brightness-90 active:brightness-75", {
  variants: {
    intent: {
      primary: "bg-blue-500 text-white border-blue-500",
      danger: "bg-red-500 text-white border-red-500",
    },
    size: {
      sm: "px-3 py-1.5 text-sm",
      md: "px-4 py-2 text-[15px]",
      lg: "px-5 py-2.5 text-[17px]",
    },
    outline: {
      true: "bg-white",
      false: "",
    },
  },
  compoundVariants: [
    { intent: "primary", outline: true, className: " !text-blue-500" },
    { intent: "danger", outline: true, className: "text-red-500" },
  ],
  defaultVariants: {
    intent: "primary",
    size: "md",
    outline: false,
  },
});

 

1. baseStyle : string[] | string

공통적으로 사용될 baseStyle을 첫번째 인자에 작성한다

tailwindCSS처럼 단순 문자열로 넣어도 되고, 배열에 각각 넣어도 된다

 

2. option {}

주로 사용하는 옵션은 아래 3가지 정도이다

- variants : 조건부 스타일을 담은 객체 (intent, size, outline ...)

- compoundVariants : variants에 담은 스타일을 조합해서 사용할 때

- defaultVariants : 기본 스타일

 

variants {}

커스텀하여 사용할 속성을 적는다

variants에 작성한 특정 속성에 따라 CSS 클래스를 적용한다

 

여기서는 intent, size, outline을 변화 속성으로 사용했다

  variants: {
    intent: {
      primary: "bg-blue-500 text-white border-blue-500",
      danger: "bg-red-500 text-white border-red-500",
    },
    size: {
      sm: "px-3 py-1.5 text-sm",
      md: "px-4 py-2 text-[15px]",
      lg: "px-5 py-2.5 text-[17px]",
    },
    outline: {
      true: "bg-white",
      false: "",
    },
  },

 

compoundVariants []

특정 조합의 변형에 따라 추가적인 클래스 이름을 정의한다

조합 안의 변형 조건이 충족될 때 적용된다

compoundVariants: [
            {
                intent: 'primary', 
                variant: 'contained',  
                className: 'bg-sky-500 ', 
            },
            {
                intent: 'primary',
                variant: 'outline',
                className: ' text-sky-500',
            },
            {
                intent: 'secondary',
                variant: 'contained',
                className: 'bg-slate-500 ',
            },
            {
                intent: 'secondary',
                variant: 'outline',
                className: ' text-slate-500',
            },
            {
                intent: 'danger',
                variant: 'contained',
                className: 'bg-red-500 ',
            },
            {
                intent: 'danger',
                variant: 'outline',
                className: ' text-red-500',
            },
        ],

 

defaultVariants

속성을 명시하지 않았을 때 기본적으로 적용될 값을 정의한다

  defaultVariants: {
    intent: "primary",
    size: "md",
    outline: false,
  },

 

 

최종적으로 코드는 다음과 같다

const buttonVariant = cva("rounded border font-semibold hover:brightness-90 active:brightness-75", {
  variants: {
    intent: {
      primary: "bg-blue-500 text-white border-blue-500",
      danger: "bg-red-500 text-white border-red-500",
    },
    size: {
      sm: "px-3 py-1.5 text-sm",
      md: "px-4 py-2 text-[15px]",
      lg: "px-5 py-2.5 text-[17px]",
    },
    outline: {
      true: "bg-white",
      false: "",
    },
  },
  compoundVariants: [
    { intent: "primary", outline: true, className: " !text-blue-500" },
    { intent: "danger", outline: true, className: "text-red-500" },
  ],
  defaultVariants: {
    intent: "primary",
    size: "md",
    outline: false,
  },
});


function Button({intent, size, outline}){
  return <button className={buttonVariant({intent, size, outline})}>Button</button>
}