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