아이콘을 버튼으로 쓰는 공통컴포넌트
disable, hover, active, default 등의 상태를 가지고 각각의 색상이 다르다
small, big 의 사이즈도 가진다
outlined 는 border가 있고 나머지 type 두개는 border가 없다
그래서 총 세가지 부분으로 컴포넌트를 나누어서 봤는데
1. 버튼 크기
2. 타입별 버튼 배경색
3. 아이콘 색상
type SizeType = 'small' | 'big';
type IconBtnType = 'solid' | 'normal' | 'outlined';
type IconButtonProps = {
type: IconBtnType;
size: SizeType;
disabled: boolean;
Icon: ReactElement;
onClick: () => void;
};
필요한 props로는 이런 것들을 받았다.
Icon을 ReactElement로 사용하는 곳에서 주입해 사용할 수 있도록 했다.
// 사이즈별 분기
const buttonSizes: Record<SizeType, SerializedStyles> = {
big: css`
width: 4rem;
height: 4rem;
`,
small: css`
width: 3.2rem;
height: 3.2rem;
`,
};
첫번째로 사이즈별 분기
// 아이콘 배경 색상 및 테두리
const getIconBtnStyles = (
strokeColor: string,
defaultBG: string,
hoverBG: string,
pressedBG: string,
border: boolean
) => {
if (disabled) {
if (type === 'solid')
return css`
background-color: ${color.Blue.Blue2};
`;
return css`
${border &&
css`
box-sizing: border-box;
border: solid 1px ${color.Grey.Grey3};
`}
`;
}
return css`
background-color: ${defaultBG};
${border &&
css`
box-sizing: border-box;
border: solid 1px ${strokeColor};
`}
:hover {
background-color: ${hoverBG};
}
:active {
background-color: ${pressedBG};
}
`;
};
const buttonStyles: Record<IconBtnType, SerializedStyles> = {
solid: getIconBtnStyles(color.Grey.White, color.Blue.Blue6, color.Blue.Blue7, color.Blue.Blue8, false),
normal: getIconBtnStyles(color.Grey.Grey5, color.Grey.White, color.Grey.Grey2, color.Grey.Grey3, false),
outlined: getIconBtnStyles(color.Grey.Grey4, color.Grey.White, color.Grey.Grey2, color.Grey.Grey3, true),
};
두번째로 배경색인데, 이부분이 좀 복잡하다. disabled인 경우 hover, active 인 상태를 막아야 하고, solid과 outlined normal이 다르다.
그런데 Outlined와 Normal은 테두리 있없 차이도 있어서 분기문을 어떻게 깔끔하게 작성할 수 있을지 고민스러웠다.
일단 선, 기본배경색, 호버시배경색, 눌렸을 때 색, 보더 유무 정도를 받아서 css 를 돌려주는 함수를 만들어, solid, normal, outlined 일때 각각 다른 css 를 받도록 했다.
경우가 많고 더러워서 그냥 저기서 css를 박아뒀어도 괜찮았을 것 같다는 생각도 든다.
이렇게 설정하고 styled 컴포넌트 안에 넣어줬다.
마지막으로 가장 걱정스러운 아이콘 색상 부분이다.
// 아이콘 색상 설정
const getIconColor = () => {
const iconColors = {
solid: theme.color.Grey.White,
normal: disabled ? theme.color.Grey.Grey4 : theme.color.Grey.Grey5,
outlined: disabled ? theme.color.Grey.Grey4 : theme.color.Grey.Grey5,
};
return iconColors[type];
};
const ColoredIcon = cloneElement(Icon, { color: getIconColor() });
이렇게 아이콘 색상을 따로 분기해서 얻고,
Icon을 reactElement로 받고 있기 때문에 props를 추가하기 위해 cloneElement 를 사용하고 얻은 색상을 props로 넘겨줬다.
svg 특성상 모양이 다른 경우가 많고 stroke 가 currentColor로 설정되어있지 않은 경우도 많아서 해당 부분을 건드리고 싶진 않았는데, 인라인 스타일이 css 스타일 건드린 것보다 우선되기 때문에 css로 stroke, fill 등 설정을 건드려봐도 적용되지 않는 문제가 있다.
일단은 이 상태로 다양한 상태를 가진 아이콘 버튼을 제작했다.
https://github.com/TEAM-DAWM/NUTSHELL-FE/pull/290
'Dev > React' 카테고리의 다른 글
공통 컴포넌트 컨트롤버튼 개발일지 (1) | 2024.11.20 |
---|---|
useTheme vs theme import (1) | 2024.11.18 |
Next.js 라우팅 (8) | 2024.05.08 |