React로 버튼 컴포넌트 만들기
버튼은 웹 에서 사용자와 상호 작용에 있어서 핵심이 되는 요소로서 하나의 웹 애플리케이션에서도 여러 종류의 버튼이 필요하기 마련입니다.
이번 포스팅에서는 다앙한 크기와 형태의 버튼을 표현하기 위해 사용할 수 있는 React로 컴포넌트를 함께 개발해보도록 하겠습니다.
컴포넌트 함수
우선 disabled
와 children
prop을 인자로 받고 아무 스타일링없이 단순히 <button>
HTML 엘리먼트를 반환하는 간단한 컴포넌트 함수를 작성합니다.
// Button.jsx
function Button({ disabled, children }) {
return <button disabled={disabled}>{children}</button>;
}
export default Button;
지금부터 React에서 Styled Components 라이브러리를 사용해서 이 버튼 컴포넌트에 필요한 스타일을 적용하도록 하겠습니다.
Styled Components에 대한 자세한 설명은 관련 포스팅를 참고 바랍니다.
기본 스타일링
버튼 컴포넌트가 어떤 상황에서 사용되든지 공통적으로 필요한 스타일을 먼저 적용해볼까요?
Styled Components로 <StyledButton/>
컴포넌트를 생성한 후, 버튼의 기본적인 스타일을 CSS로 정의해줍니다.
여기서 버튼 종류의 따라 바뀔 수 있는 속성값에는 CSS 변수(CSS variable, CSS custom property)를 사용하였습니다.
이제 컴포넌트 함수가 반환하는 값을 <button>
엘리먼트가 아닌 <StyledButton/>
컴포넌트로 교체해줍니다.
// Button.jsx
import styled from "styled-components";
function Button({ disabled, children }) {
return <StyledButton disabled={disabled}>{children}</StyledButton>;
}
const StyledButton = styled.button`
margin: 0;
border: none;
cursor: pointer;
font-family: "Noto Sans KR", sans-serif;
font-size: var(--button-font-size, 1rem);
padding: var(--button-padding, 12px 16px);
border-radius: var(--button-radius, 8px);
background: var(--button-bg-color, #0d6efd);
color: var(--button-color, #ffffff);
&:active,
&:hover,
&:focus {
background: var(--button-hover-bg-color, #025ce2);
}
&:disabled {
cursor: default;
opacity: 0.5;
background: var(--button-bg-color, #025ce2);
}
`;
export default Button;
크기 스타일링
여러 가지 크기를 지원하는 버튼 컴포넌트를 만들기 위해서 size
라는 prop을 추가합니다.
버튼 크기에 영향을 줄 수 있는 CSS 변수를 Styled Components의 css
함수를 사용하여 SIZES
라는 자바스크립트 객체 저장해두었습니다.
// Button.jsx
import styled, { css } from "styled-components";
const SIZES = {
sm: css`
--button-font-size: 0.875rem;
--button-padding: 8px 12px;
--button-radius: 4px;
`,
md: css`
--button-font-size: 1rem;
--button-padding: 12px 16px;
--button-radius: 8px;
`,
lg: css`
--button-font-size: 1.25rem;
--button-padding: 16px 20px;
--button-radius: 12px;
`,
};
function Button({ disabled, size, children }) {
const sizeStyle = SIZES[size];
return (
<StyledButton disabled={disabled} sizeStyle={sizeStyle}>
{children}
</StyledButton>
);
}
const StyledButton = styled.button`
${(p) => p.sizeStyle}
margin: 0;
border: none;
cursor: pointer;
/* 이하 생략 */
`;
export default Button;
변형 스타일링
성공, 오류, 경고 등 여러 상황에서 활용이 가능한 버튼 컴포넌트를 만들기 위해서 variant
라는 prop을 추가합니다.
마찬가지 방법으로 버튼 형태에 영향을 줄 수 있는 CSS 변수를 Styled Components의 css
함수를 사용하여 자바스크립트 객체 VARIANTS
라는 자바스크립트 객체 저장해두었습니다.
// Button.jsx
import styled, { css } from "styled-components";
const SIZES = {
// 생략
};
const VARIANTS = {
success: css`
--button-color: #ffffff;
--button-bg-color: #28a745;
--button-hover-bg-color: #218838;
`,
error: css`
--button-color: #ffffff;
--button-bg-color: #dc3545;
--button-hover-bg-color: #c82333;
`,
warning: css`
--button-color: #212529;
--button-bg-color: #ffc107;
--button-hover-bg-color: #e0a800;
`,
};
function Button({ disabled, size, variant, children }) {
const sizeStyle = SIZES[size];
const variantStyle = VARIANTS[variant];
return (
<StyledButton
disabled={disabled}
sizeStyle={sizeStyle}
variantStyle={variantStyle}
>
{children}
</StyledButton>
);
}
const StyledButton = styled.button`
${(p) => p.sizeStyle}
${(p) => p.variantStyle}
margin: 0;
border: none;
cursor: pointer;
/* 이하 생략 */
`;
export default Button;
전체 코드
본 포스팅에서 작성한 코드는 아래에서 직접 확인하고 실행해볼 수 있습니다.
마치면서
이상으로 React와 Styled Components를 사용해서 재사용이 용이한 버튼 컴포넌트를 만들어보았습니다.
많은 React 프로젝트에서 이렇게 하나의 버튼 컴포넌트를 만들어 놓고 여러 컴포넌트에서 재사용하는 패턴이 많이 사용됩니다. 필요할 때 마다 매번 처음부터 버튼 컴포넌트를 만들면 중복해서 코딩을 해야 할 뿐만 아니라 일관성있는 UI를 제공하기 어려워지기 때문입니다.