9. Styled-components : Polished 스타일 유틸 함수 사용 - 컴포넌트 스타일링 | 벨로퍼트
Sass 를 사용 할 때에는 lighten() 또는 darken() 과 같은 유틸 함수를 사용하여 색상에 변화를 줄 수 있었는데요, CSS in JS 에서도 비슷한 유틸 함수를 사용하고 싶다면 polished 라는 라이브러리를 사용하면 됩니다.
우선, 패키지를 설치를 해주세요.
$ yarn add polished
그럼, 기존에 색상 부분을 polished 의 유틸 함수들로 대체를 해보겠습니다.
/src/components/Button.js :
// ...
import { darken, lighten } from 'polished';
const StyledButton = styled.button`
// ...
/* 색상 */
background: #228be6;
&:hover {
background: ${lighten(0.1, '#228be6')};
}
&:active {
background: ${darken(0.1, '#228be6')};
}
// ...
`;
버튼에 커서를 올렸을 때 색상이 잘 바뀌고 있나요?
이제 회색, 핑크색 버튼들을 만들어볼건데요, 색상 코드를 지닌 변수를 Button.js 에서 선언을 하는 대신에 ThemeProvider 라는 기능을 사용하여 styled-components 로 만드는 모든 컴포넌트에서 조회하여 사용 할 수 있는 전역적인 값을 설정해보겠습니다.
App.js 를 다음과 같이 수정해보세요.
/src/App.js :
import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import Button from './components/Button';
// ...
function App() {
return (
<ThemeProvider
theme={{
palette: {
blue: '#228be6',
gray: '#495057',
pink: '#f06595'
}
}}
>
<AppBlock>
<Button>BUTTON</Button>
</AppBlock>
</ThemeProvider>
);
}
이렇게 해서 theme 을 설정하면 ThemeProvider 내부에 렌더링된 styled-components 로 만든 컴포넌트에서 palette 를 조회하여 사용 할 수 있습니다. 한번 Button 컴포넌트에서 우리가 방금 선언한 palette.blue 값을 조회해봅시다.
/src/components/Button.js :
// ...
import styled, { css } from 'styled-components';
const StyledButton = styled.button`
// ...
/* 색상 */
${props => {
const selected = props.theme.palette.blue;
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}
// ...
`;
ThemeProvider 로 설정한 값은 styled-components 에서 props.theme 로 조회 할 수 있습니다. 지금은 selected 값을 무조건 blue 값을 가르키게 했는데요, 이 부분을 Button 컴포넌트가 color props를 통하여 받아오게 될 색상을 사용하도록 수정해보겠습니다.
/src/components/Button.js :
const StyledButton = styled.button`
// ...
/* 색상 */
${props => {
const selected = props.theme.palette[props.color];
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}
// ...
`;
function Button({ children, color ...rest }) {
return <StyledButton {...rest}>{children}</StyledButton>
}
Button.defaultProps = {
color: 'blue'
};
지금은 기본 색상이 blue 가 되도록 설정해주었습니다.
이제 App 컴포넌트를 열어서 회색, 핑크색 버튼을 렌더링해봅시다.
/src/App.js :
// ...
function App() {
return (
<ThemeProvider
theme={{
palette: {
blue: '#228be6',
gray: '#495057',
pink: '#f06595'
}
}}
>
<AppBlock>
<Button>BUTTON</Button>
<Button color="gray">BUTTON</Button>
<Button color="pink">BUTTON</Button>
</AppBlock>
</ThemeProvider>
);
}
// ...
결과가 잘 나타났나요?
Button 컴포넌트의 코드는 다음과 같이 리팩토링 할 수 있습니다.
/src/components/Button.js :
const StyledButton = styled.button`
// ...
/* 색상 */
${({ theme, color }) => {
const selected = theme.palette[color];
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}
// ...
`;
function Button({ children, color, ...rest }) {
return <StyledButton color={color} {...rest}>{children}</StyledButton>;
}
props.theme.palette.blue 이런식으로 값을 조회하는 대신에 비구조화 할당 문법을 사용하여 가독성을 높여주었습니다.
참고로 위 로직은 다음과 같이 색상에 관련된 코드를 분리하여 사용 할 수도 있습니다.
/src/components/Button.js :
const colorStyles = css`
${({ theme, color }) => {
const selected = theme.palette[color];
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}
`;
const StyledButton = styled.button`
// ...
/* 색상 */
${colorStyles}
// ...
`;
작업을 다 하셨다면, 이전과 동일하게 작동하는지 확인해보세요.