[ React ] Next.js 에서 Class Variance Authority를 사용하여 유연한 버튼 컴포넌트 만들기

이준혁·2024년 6월 25일
1
post-thumbnail

버튼 컴포넌트는 다양한 스타일과 기능을 필요로 하기 때문에 유연하게 만드는 것이 특히 중요합니다. 이번 블로그 포스트에서는 class-variance-authority (CVA) 라이브러리를 사용하여 !
애플리케이션에서 유연한 버튼 컴포넌트를 만드는 방법을 살펴보겠습니다.

사전 준비

class-variance-authority 설치

npm install class-variance-authority

코드 작성

버튼 컴포넌트를 작성할 때, CVA를 사용하여 다양한 스타일 옵션을 쉽게 정의할 수 있습니다. 아래는 그 예시입니다:

import { VariantProps, cva } from "class-variance-authority";
import Link from "next/link";
import { ComponentProps, PropsWithChildren } from "react";

const buttonVariant = cva("border rounded font-semibold transition hover:brightness-90 active:brightness-75", {
  variants: {
    intent: {
      primary: "border-sky-500",
      secondary: "border-slate-500",
      danger: "border-red-500",
    },
    size: {
      sm: "px-3 py-1 text-[13px]",
      md: "px-4 py-1.5 text-[15px]",
      lg: "px-5 py-2 text-[17px]",
    },
    variant: {
      outline: "bg-white",
      contained: "text-white",
    },
  },
  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: {
    intent: "primary",
    size: "md",
    variant: "contained",
  },
});

type ButtonVariant = VariantProps<typeof buttonVariant>;

type ButtonProps = ButtonVariant & (({} & ComponentProps<"button">) | ({ href: string } & ComponentProps<typeof Link>));

function Button({ intent, size, variant, children, ...props }: PropsWithChildren<ButtonProps>) {
  if ("href" in props) {
    return (
      <a className={buttonVariant({ intent, size, variant })} {...props}>
        {children}
      </a>
    );
  } else {
    return (
      <button className={buttonVariant({ intent, size, variant })} {...props}>
        {children}
      </button>
    );
  }
}

export default Button;

설명

  1. CVA 설정: buttonVariant 객체를 사용하여 버튼의 다양한 스타일 옵션을 정의합니다. intent, size, variant 등의 변형을 설정할 수 있습니다.
  2. 타입 정의: ButtonVariant 타입과 ButtonProps 타입을 정의하여 TypeScript에서 사용합니다.
  3. Button 컴포넌트: Button 컴포넌트를 작성하여, href 속성이 있으면 Link 컴포넌트를 사용하고, 그렇지 않으면 button 태그를 사용합니다.

이와 같은 방식으로 버튼 컴포넌트를 유연하게 설정하면, 다양한 스타일과 기능을 쉽게 적용할 수 있습니다. CVA를 활용하여 복잡한 스타일링을 단순하게 관리해보았습니다.

0개의 댓글