typescript와 next.js에서 tailwind와 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'>부분을 넣어주는 것을 제대로 이해하지 못했다. 내일 더 마저 공부해야겠다.