블로그의 모드를 전환하기 위해선, 스위치(혹은 버튼)가 필요하다.
이 블로그에선 헤더의 우측 상단에 보이는 스위치이다.

switch

상단 스위치를 직접 눌러보세요!

(현재는 모양이 바뀐 상태)

따로 Switch.js 컴포넌트로 작성하고 필요한 것을 부모페이지에서 prop으로 내려받을 것이다.

🎯 이 블로그에서 Switch를 만들때 고려한 점은 다음과 같다.

  1. A/B 두가지 상태 반복 전환
  2. 디자인이 스위치 모양

Form-checkbox

다크모드를 변환시키는 스위치 혹은 버튼은 기본적으로 toggle이다. Toggle이란 상태가 두 가지만 존재하여, A 아니면 B, 두가지 상태 사이에서 전환을 반복하는 것을 의미한다. 예를 들면 형광등 스위치, 컴퓨터의 caps lock 등이 대표적인 예이다.

두 가지 선택지만 존재하여 반복하는 것으로 스위치를 만들어야 한다. html에서 두가지 선택지로 반복하는 대표적인 태그는 체크박스 <input type="checkbox">이다. check/uncheck 사이를 반복하며 전환하기 때문이다.

gun-switch

미스터빈의 일회용(?) 스위치

checked

리액트에서 Form-checkbox를 다룰때, <input type="checkbox">에서 체크 여부를 담당하는 속성은 checked이다. 에선 checked속성에 따라 체크 여부가 달라지는 것이다.

components/Switch.js
import React from 'react';

const Switch = (props) => {
  const { isChecked } = props;

  return (
    <div className="switch">
      <input
        type="checkbox"
        checked={isChecked}
      />
    </div>
  );
};

export default Switch;

속성 checked={isChecked}에서 대괄호 속 isChekced 값이 true면 체크되고, false면 체크해제 되는 것이다. 즉, checked는 박스가 체크표시를 할지 말지 판단하는 기준이라고 보면 된다.

onChange

그렇다면 checked값은 어떻게 변경해야 할까.
리액트에선 onChange 속성을 이용하면 된다.

onChange는 폼 필드가 변경될때 실행하는 이벤트이다. 체크박스에선, 체크가 될때마다 실행하는 이벤트이다.(텍스트박스라면, 글자가 입력될때마다 실행된다.)

components/Switch.js
import React from 'react';

const Switch = (props) => {
  const { isChecked, handleToggle } = props;

  return (
    <div className="switch">
      <input
        type="checkbox"
        checked={isChecked}
        onChange={handleToggle}
      />
    </div>
  );
};

export default Switch;

checked 값을 state로 관리하고, onChange라는 속성에 state를 변경하는 함수(여기서는 handleToggle)를 받아서 관리할 것이다.

label

체크박스는 스타일링하는건 어렵다. 그래서 라벨을 만들어 원하는 모양으로 스타일링 한후, 체크박스와 연결하고 진짜 체크박스는 숨기는 것이 보통이다.

여기서 만드는 스위치의 형태는 가운데의 원형 볼className="ball"이 좌우로 움직이는 형태이므로, label태그 사이에 관련 div를 넣어준다.

components/Switch.js
import React from 'react';

const Switch = (props) => {
  const { isChecked, handleToggle } = props;

  return (
    <div className="switch">
      <input
        type="checkbox"
        className={`switch-checkbox`}
        checked={isChecked}
        onChange={handleToggle}
        id={`switch-input`}  // label의 htmlFor에 걸어줄 id
      />
      <label
        className={`switch-label`}
        htmlFor={`switch-input`}  // input id를 걸어준다
      >
        <div className="ball" />  // 스위치 속 좌우로 움직이는 ball
      </label>
    </div>
  );
};

export default Switch;

scss

스위치 모양으로 스타일링해보자.

  1. input 체크박스 안보이게, 양쪽이 둥근 틀, 가운데 볼
  2. 가운데 원형 볼이 체크에 따라 좌우로 부드럽게 움직이기
  3. 스위치 볼색, 배경색 변화

테마별 색상을 다르게 설정하기 위해, Custom properties로 색상을 설정한다.
Custom properties(사용자 지정 속성)는 css 작성자가 재사용이 가능하도록 변수를 정의하고 값을 할당하는 것이다.

.switch-checkbox {
  // 1. input 체크박스 가리기
  display: none;

  // 2. 체크시 볼의 css
  &:checked + .switch-label-theme .ball {
    transform: translateX(24px);  // 체크시 볼의 이동거리
}

.switch-label {
  // 1. 양쪽이 둥근 스위치
  position: relative;
  height: 26px;
  width: 50px;
  border-radius: 50px;

  // 3. 색상 - 스위치 배경
  background-color: var(--switch-bg-color);
}

.ball {
  // 1. 스위치 볼
  position: absolute;
  height: 22px;
  width: 22px;
  border-radius: 50%;
  top: 2px;
  left: 2px;

  // 2. 이동시 부드럽게
  transition: transform 0.2s linear;

  // 3. 색상 - 스위치 볼
  background-color: var(--ball-color);
}

마무리

현재는 모양이 바뀐 상태이지만, 포스트로 작성한 스위치는 많이 쓰이는 기본적인 모양이다. checkbox를 사용해서 리액트에서 checkbox form도 정리해보았다. 또한 label로 checkbox를 스타일링 하면서, transition 효과도 넣어야하고, 색상도 변화시키고... 크기는 작지만 다양하게 이것저것 많은 css를 연습해 볼 수 있었다.

Reference & Learn More

React Form
MDN Custom properties

Comments