따로 정의한 palette와 typography의 mui theme를 활용해 mui Button을 커스텀하여 재사용이 가능하도록 기능을 구현할 것이다.
// 패딩 사이즈 표
const PADDING = {
xl: '14px 17.5px',
lg: '12px 14px',
md: '10px 12px',
sm: '8px 12px',
};
import { ButtonProps } from '@mui/material';
// 버튼 타입들
export type Color = 'primary' | 'secondary';
export type Variant = 'text' | 'outlined' | 'contained';
export type Size = 'xl' | 'lg' | 'md' | 'sm';
interface BoxButtonProps extends ButtonProps {
// 버튼명
title: string;
// 버튼 배경 색상
color?: Color;
// 버튼 모양
variant?: Variant;
// 버튼 사이즈
padding?: Size;
}
import { useTheme } from '@mui/material';
const BoxButton = ({
title,
variant,
color, // secondary가 오거나 primary가 오거나
padding,
disabled,
...others
}: BoxButtonProps) => {
const theme = useTheme(); // 팔레트 색상을 활용하기 위해
// 버튼 색상 분기 처리
let backgroundColor = color as string;
if (color === 'secondary') {
backgroundColor = theme.palette.grey[900] as string;
}
if (disabled) {
backgroundColor = theme.palette.grey[200] as string;
}
interface StyleProps {
padding: string;
backgroundColor: string;
}
const MuiButton = styled(Button, {
shouldForwardProp: (prop) => prop !== 'padding' && prop !== 'backgroundColor',
})(({ padding, backgroundColor }: StyleProps) => ({
backgroundColor,
padding: padding as string,
margin: 5,
}));
styled(Button, { shouldForwardProp }):
styled 함수는 Button 컴포넌트를 커스터마이즈하기 위한 스타일을 생성하는 함수입니다.
이 함수는 전달된 prop이 'padding'이거나 'backgroundColor'가 아닌 경우에만 true를 반환합니다. 즉, 'padding'과 'backgroundColor' 속성은 스타일 컴포넌트에 전달되지 않고, 나머지 속성들은 실제 Button 컴포넌트로 전달됩니다.
return (
<MuiButton
theme={theme}
variant={variant}
backgroundColor={backgroundColor as string}
padding={PADDING[padding as Size]}
disabled={disabled}
{...others}
>
<Typography
variant="h5"
color={!disabled && variant === 'outlined' ? color : 'white'}
>
{title}
</Typography>
</MuiButton>
);
BoxButton.defaultProps = {
color: 'primary',
variant: 'contained',
padding: 'lg',
};
<BoxButton
title="버튼"
color="primary"
padding="xl"
onClick={handleClick}
/>
<BoxButton
title="버튼"
color="primary"
padding="lg"
onClick={handleClick}
/>
<BoxButton
title="버튼"
color="primary"
padding="md"
onClick={handleClick}
/>
<BoxButton
title="버튼"
color="primary"
padding="sm"
onClick={handleClick}
/>