[내배캠] 6/24

초이·2024년 6월 24일
0

🗓️ 내일배움캠프

목록 보기
42/55
post-thumbnail
post-custom-banner

재사용성 높은 컴포넌트

typescript와 next.js에서 tailwind와 cva를 이용해서 컴포넌트를 재사용하는 법에 대해 배웠다.

CVA란

cva([공통으로 들어갈 값],{ variants: {}, defaultVariants:{}, compoundVariants:[] });

이렇게 사용되는데,

  • variants는 안에 props에 넣은 값의 이름이 일치하는 것을 찾아 className에 이름에 해당하는 값을 넣는것이다.

따라서, props로 size, intent, variant등등 값을 넣어주면 size가 md에 적혀져있는 string을 공통으로 들어갈 값 뒤에 className으로 붙여주는 것이다.

  • compoundVariants는 조건문과 같이 쓰이는데, props color의 값이 red이고 size가 md일 때만 className에 해당 str를 붙여준다.

  • defaultVariants는 해당 컴포넌트를 쓰는데, 아무런 props를 가져다 쓰지 않으면 기본으로 설정된 값을 적어 주는 것이다.



코드로 나타내면 이렇다.

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


이것을 컴포넌트에 적용하기 위해 ButtonVariant의 타입을 VariantProps로 지정해둔 것을 ButtonProps에 저장하고 함수에 PropsWithChildren에 타입으로 지정해두면 내가 지정한 값들을 컴포넌트를 사용할 때, 어떤 props가 필요한지 알 수 있다.

type ButtonVariant = VariantProps<typeof buttonVariant>;

type ButtonProps = {} & ButtonVariant & ComponentProps<"button">;

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

export default Button;

아직 typescript가 익숙하지 않아서 ComponentProps<'button'>부분을 넣어주는 것을 제대로 이해하지 못했다. 내일 더 마저 공부해야겠다.

profile
개발 일기장
post-custom-banner

0개의 댓글