SurveyProject) 스타일변수 만들기(feat.style-components)

iamokian·2022년 7월 27일
0

설문폼 프로젝트를 클론코딩해보며 이것저것 새로 알기도하고, 알던걸 또 되새기며 조금씩 깨우치고있다. 그중 style-components를 사용하며 이렇게도 쓰는구나를 배운것이 있다.(style-components를 사용하는 법이기도하지만 CSS-in-JS의 사용법? 편리함? 이라고 봐야할까)

하나의 버튼 컴포넌트에 위와 같이 다양한 타입 그리고 한타입에서 또 세부적으로 다른 스타일링의 무언가를 상황별로 그려내려 할때, 단순히 if 문이나 함수를 써가면서도 만들 수 있겠지만 스타일변수를 만들어두고 타입들을 props로 받아 스타일을 주면 코드도 간결해지고 편리하다는것을 알게되었다.

function ActionButtons({ questionsLength, step }) {
  const isLast = questionsLength - 1 === step;
  const navigate = useNavigate();
  return (
    <ActionButtonsWrapper>
      {/* 스텝넘버가 0이라면 이전버튼은 노출되지않고 0 다음 숫자일 경우 이전버튼 그리기 */}
      {step === 0 || (
        <Button
          type="TERTIARY"
          onClick={() => {
            navigate(`${step - 1}`);
          }}
        >
          이전
        </Button>
      )}
      {/* isLast에있는 questionsLength가 마지막번호가 아니라면 다음버튼이 보여지고 마지막번호라면 제출번호 그리기 */}
      {isLast ? (
        <Button
          type="PRIMARY"
          onClick={() => {
            navigate('/done');
          }}
        >
          제출
        </Button>
      ) : (
        <Button
          type="PRIMARY"
          onClick={() => {
            navigate(`${step + 1}`);
          }}
        >
          다음
        </Button>
      )}
    </ActionButtonsWrapper>
  );
}

위 코드는 저 버튼들이 어떤상황에서 노출될지, 아닐지 상황을 따로 그려놓은 코드. 저 코드에서 중요한건 버튼마다 type을 props로 버튼에게 내려주고 있는것이다.

export const PRIMARY = {
  BUTTON: {
    DEFAULT: {
      COLOR: '#fff',
      BACKGROUND: '#6542F1',
    },
    HOVER: {
      COLOR: '#fff',
      BACKGROUND: '#9982F4',
    },
    PRESSED: {
      COLOR: '#fff',
      BACKGROUND: '#4B31B0',
    },
    DISABLED: {
      COLOR: '#D0CDCD',
      BACKGROUND: '#EDEDED',
    },
  },
};

export const SECONDARY = {
  BUTTON: {
    DEFAULT: {
      COLOR: '#3A3A3A',
      BACKGROUND: '#DEDEDE',
    },
    HOVER: {
      COLOR: '#3A3A3A',
      BACKGROUND: '#F3F3F3',
    },
    PRESSED: {
      COLOR: '#3A3A3A',
      BACKGROUND: '#B8B7B9',
    },
    DISABLED: {
      COLOR: '#D0CDCD',
      BACKGROUND: '#EDEDED',
    },
  },
};

export const TERTIARY = {
  BUTTON: {
    DEFAULT: {
      COLOR: '#6542F1',
      BACKGROUND: '#fff',
      BORDER: '#6542F1',
    },
    HOVER: {
      COLOR: '#9982F4',
      BACKGROUND: '#fff',
      BORDER: '#9982F4',
    },
    PRESSED: {
      COLOR: '#4B31B0',
      BACKGROUND: '#F0EDFC',
      BORDER: '#4B31B0',
    },
    DISABLED: {
      COLOR: '#D0CDCD',
      BACKGROUND: '#F6F6F6',
      BORDER: '#EDEDED',
    },
  },
};

이것이 최상위 이미지에 있는 버튼 스타일들을 변수화시켜서 정리해둔것! 폴더와 페이지도 따로 빼서 관리하니 이런식의 변수는 이곳에서 하면 된다.

import styled from 'styled-components';

// 선언해둔 스타일변수 가져오기
import { PRIMARY, SECONDARY, TERTIARY } from '../../constants/color';

// 가져온 스타일변수 이곳에서 꺼내쓰기 쉽게 객체로 다시 그룹핑
const colorMap = {
  PRIMARY,
  SECONDARY,
  TERTIARY,
};

const Button = styled.button`
  width: 200px;
  padding: 16px 24px;
  border-radius: 4px;
// 순수 css가 아니므로 이곳에서 함수를 사용할 수 있다. ${}를 사용하자
// style-components도 props를 받을 수 있다.
// 부모 컴포넌트가 내려준 props를 사용해 버튼스타일링을 할 수 있다.
  color: ${({ type }) => colorMap[type].BUTTON.DEFAULT.COLOR};
  background: ${({ type }) => colorMap[type].BUTTON.DEFAULT.BACKGROUND};
  font-weight: bold;

// 아래 타입은 경우에 따라 border가 생긴다. 삼항연산자로 처리
  border: ${({ type }) =>
    type === 'TERTIARY'
      ? `1px solid ${TERTIARY.BUTTON.DEFAULT.BORDER}`
      : 'none'};

  &:hover {
    color: ${({ type }) => colorMap[type].BUTTON.HOVER.COLOR};
    background: ${({ type }) => colorMap[type].BUTTON.HOVER.BACKGROUND};
    border: ${({ type }) =>
      type === 'TERTIARY'
        ? `1px solid ${TERTIARY.BUTTON.HOVER.BORDER}`
        : 'none'};
  }

  &:active {
    color: ${({ type }) => colorMap[type].BUTTON.PRESSED.COLOR};
    background: ${({ type }) => colorMap[type].BUTTON.PRESSED.BACKGROUND};
    border: ${({ type }) =>
      type === 'TERTIARY'
        ? `1px solid ${TERTIARY.BUTTON.PRESSED.BORDER}`
        : 'none'};
  }

  &:disabled {
    color: ${({ type }) => colorMap[type].BUTTON.DISABLED.COLOR};
    background: ${({ type }) => colorMap[type].BUTTON.DISABLED.BACKGROUND};
    border: ${({ type }) =>
      type === 'TERTIARY'
        ? `1px solid ${TERTIARY.BUTTON.DISABLED.BORDER}`
        : 'none'};
  }
`;

export default Button;

복잡해보이지만 나름 선언해둔 스타일변수로 인해 깔끔해진편이다. if문으로 분개했다면 엄청 길어졌을것이니..

profile
필기하고 기록하고

0개의 댓글