개발
props 타입 상속으로 시맨틱 태그에 테마 적용 하기
배우겠습니다
2024. 4. 4. 17:38
frame work
- vanilla extract, nextjs
- react와 css(+module)를 사용해도 상관 없다.
문제 상황
- 만약에 props로 스타일링만 제어하고 나머지 버튼의 기능은 사용하고 싶다고 하자.
- props를 설정할 때 모든 버튼의 attributes를 적어주는건 매우 고된 일이다. 게다가 버튼말고도 다른 태그에도 이런 요구사항이 있다면?
- 하나하나 적다가 빼먹거나 잘못적는 attribute가 나올수도 있고, 기존 내가 추가로 넣을 props를 관리하기도 어려워진다.
- 각 attribute마다 정확한 타입을 적용하는 것도 태스크가 많이 들어갈 것이다.
해결
React는 이미 내부적으로 각 태그마다 props의 타입을 정의해 놓았고 export 시켜놓았다.
DetailedHTMLProps<XXXHTMLAttributes<HTMLXXXElement>,HTMLXXXElement> // 예를들어 button은 DetailedHTMLProps< ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement >
우린 위 타입을 사용하지 않을 이유가 없다.
타입 상속으로 위 타입을 받아오고 우리는 우리가 추가로 설정할 props만 적용하면 된다.
interface PropType extends DetailedHTMLProps< ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement > { size?: "small" | "medium" | "large"; color?: "primary" | "negative" | "positive" | "white"; fullWidth?: boolean; flat?: boolean; children?: ReactNode; // 추가적인 props }
그럼 PropType에는 react buttom element의 attribute로 가능한 것들을 이미 사용할 수 있다.
하지만 실제로 이걸 이용해 태그에 attribute를 적용하는 방법은 아직은 미지수이다.
export default function Button({ size = "medium", color = "primary", children, fullWidth = false, flat = false, ...props }: PropType) { return ( <button {...props} > {children} </button> ); }
스프레드를 이용해, 우리가 추가적으로 선언한 것 외의 props = attributes of button tag를 받아올 수 있다.
따라서 이것을 버튼에 적용시켜주면 된다.
스타일링 적용: Vanilla extract
순수한 css를 사용하겠다고 한다면 pass
이제 props의 값에 따라 className을 변형시켜 버튼의 스타일을 조정할 수 있다.
recipe는 variant값에 따른 className을 리턴시켜준다.
const buttonStyle = recipe({ base: { // 버튼에 적용할 기본적인 스타일 }, variants: { 변수1:{ 값1:{ //style }, 값2:{ //style }, }, 변수2:{ 값1:{ //style }, 값2:{ //style }, } }, }); export default buttonStyle;
- 이제 이걸 button tag의 className에 넣어준다.
className={classNames(
props?.className, // 추가적으로 선언하고 싶은 스타일
buttonStyle({
color: color, // props로 color size fullWidth flat을 받아온다.
size: size,
fullWidth: fullWidth,
flat: flat,
})
)