styled-component로 다크 모드 구현하기

hoi·2020년 9월 21일
4
post-thumbnail

시작 전 🧐

React + TypeScript 환경에서 styled-component를 declare하는 방법은 React 카테고리 블로그 포스팅에서 다루고 있습니다. 간단한 주제를 다루고 있으니 궁금하신 부분은 해당 내용을 참고해 주세요.

무엇을 활용해 구현하는가 ?

styled-component에 내장된 ThemeProvider를 활용해서 구현합니다. ThemeProvider는 React Context API와 같이 지정한 테마를 자식 컴포넌트에 전달하며 자식 컴포넌트는 useContext와 ThemeContext를 활용하여 컴포넌트 내부에서 그 값을 활용할 수도 있고 styled-component는 color : ${(props)⇒ props.theme.baseColor }; 와 같은 표기법으로 지정한 테마의 값을 사용할 수도 있습니다.

테마 분류하기

우선 라이트 모드 , 다크 모드에 사용될 테마를 각각 지정해 줍니다. 점점 각 모드를 구분하는 테마의 속성은 늘어나겠지만 일단 기본적으로 background-color , color에 대한 값을 지정해 줬습니다.

// DefaultTheme.ts

export const darkTheme: DefaultTheme = {
  basicBg: "#1E2022",
  basicFont: "#fff",
  basicContextBox : "#828282",
};

export const lightTheme: DefaultTheme = {
  basicBg: "#f7f6f2",
  basicFont: "#4c3f36",
  basicContextBox : "#fff",
};

GlobalStyle에 Theme 지정하기

이 후 GlobalStyle에 basicFont와 basicBg를 적용해 줬습니다. 특정 색상을 따로 적용하지 않는 이상 color와 background-colors는 theme로 전달받은 값을 활용하여 색상을 구성할 것 입니다.

// GlobalStyle.ts
export const GlobalStyle = createGlobalStyle`
  ${reset}

  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family : 'Source Sans Pro' , sans-serif;
  }

  body {
    color : ${(props) => props.theme.basicFont};
    background-color : ${(props) => props.theme.basicBg};
    position : relative;
  }

ThemeProvider로 전달하기

위에서 구현한 테마와 GlobalStyle을 App.tsx에 전달해 줍니다. 이 때 isDark라는 Boolean Type의 상태를 두고 그 값을 바꿀 수 있는 changeTheme를 만들어 줬습니다. 이 후 Switch Component를 통해서 사용자가 테마를 변경할 수 있는 기능을 제공합니다.

// App.tsx
import { ThemeProvider } from "styled-components";
import { darkTheme, lightTheme } from "./styles/DefaultTheme";
import GlobalStyle from "./styles/GlobalStyle";

function App() {
  const [isDark, setIsDark] = useState(false);

  function changeTheme() {
    setIsDark(!isDark);
  }

  return (
    <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
      <GlobalStyle />
      <Header />
      <Switch changeTheme={changeTheme} isDark={isDark} />
    </ThemeProvider>
  );
}

Switch Component 구현하기

Switch Component를 아래와 같이 구성하여 현재 테마에 따라서 다른 텍스트를 제공하고 클릭으로 테마를 변경할 수 있도록 Component를 구성해 줬습니다.

// Switch.tsx
import React from "react";
import { SwitchWrapper } from "./Switch.element";

interface ISwitch {
  changeTheme: (event: React.MouseEvent) => void;
  isDark: Boolean;
}

function Switch({ changeTheme, isDark }: ISwitch) {
  return (
    <SwitchWrapper onClick={changeTheme}>
      {isDark ? "🌝 라이트 모드로 보기" : "🌚 다크 모드로 보기"}
    </SwitchWrapper>
  );
}

export default Switch;

// SwitchWrapper

export const SwitchWrapper = styled.button`
  position: fixed;
  bottom: 5%;
  right: 5%;

  background-color: ${(props) => props.theme.basicThemeBtnBg};
  color: ${(props) => props.theme.basicFont};
  font-size: 16px;
  font-weight: bold;

  padding: 4px 12px;
  border-radius: 8px;
  box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
`;

구현 화면

간단한 텍스트를 띄운 후 작동하는 화면은 아래와 같습니다.

후기 🤓

다크 모드의 취지는 모바일 환경에서 좀 더 익숙한 다크 모드라는 기능을 웹에서도 지원하게 하자는 의미에서 기능을 추가하게 됐습니다. 또한 이런 스타일 요소는 이미 진행된 프로젝트에선 쉽게 적용하기 힘든 부분이 있어 초기에 다크 모드의 기능을 염두하고 환경을 구성하게 됐습니다. 일단 예제 코드는 간단한 색상을 지정해서 사용했지만 추후 기능 추가에 따라서 모드에 맞는 테마 컬러를 지정 하면서 속성을 확장해 나갈 예정입니다.

profile
왕초보

0개의 댓글