Front-end/React.js

9. Styled-components : Polished 스타일 유틸 함수 사용 - 컴포넌트 스타일링 | 벨로퍼트

AGAL 2020. 7. 20. 11:08
반응형

 

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}

  // ... 
`;

작업을 다 하셨다면, 이전과 동일하게 작동하는지 확인해보세요.

반응형