image

다크모드 적용 (next-themes)

태그
Next.js
상세설명next-themes로 다크모드 적용하는 방법
작성일자2023.10.20

현재 개인 블로그를 만들면서 다크모드를 next-themes 라는 라이브러리를 사용해서 적용해보았다.

개인 블로그 css를 tailwind로 적용했기 때문에 tailwind 방식으로 진행했다.

tailwind.config.js 수정

config중 darkMode를 ”class” 로 바꾼다.

“class”로 수정해야 수동으로 어두운 모드 전환할 수 있다.

기본형은 “media” 로 운영 체제 기본 설정에 의존한다.

import type { Config } from "tailwindcss";

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  darkMode: "class",
  theme: {
    extend: {
      .....
    },
  },
  plugins: [],
};
export default config;

next-themes 설치 & 사용법

next-themes 라이브러리

npm i next-themes

설치 후 next-themes에 있는 ThemeProvider Component 를 감싸야된다.

그리고 클래스를 사용하여 테마에 따라 페이지 스타일을 지정할 거기 때문에 attribute="class" 추가한다.

//_app.tsx

import type { AppProps } from "next/app";
import { ThemeProvider } from 'next-themes'

function App({ Component, pageProps }: AppProps) {
  return (
    <ThemeProvider attribute="class">
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

export default MyApp

DarkModeToggleBtn 라는 컴포넌트에 라이트, 다크모드 버튼을 만들고 Header영역에 배치 시켰다.

// components/darkModeToggleBtn.tsx

import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
import { HiOutlineSun, HiOutlineStar } from "react-icons/hi";

export default function DarkModeToggleBtn() {
  const { theme, setTheme } = useTheme();
  const [loaded, setLoaded] = useState(false);
  useEffect(() => {
    setLoaded(true);
  }, [setLoaded]);

  return (
    <button
      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
      className="flex p-1"
    >
      {loaded ? (
        <>
          {theme === "dark" ? (
            <HiOutlineStar className="text-2xl text-yellow-500" />
          ) : (
            <HiOutlineSun className="text-2xl" />
          )}
        </>
      ) : null}
    </button>
  );
}

Header에 배치

// components/header.tsx

import Link from "next/link";
import DarkModeToggleBtn from "./darkModeToggleBtn";
import { useRouter } from "next/router";
import { cls } from "libs/utils";

export default function Header() {
  const router = useRouter();
  return (
    <header className="fixed top-0 z-50 bg-primary w-full">
      <div className="max-w-3xl flex items-center justify-between py-2 px-4 lg:px-0 mx-auto">
        <nav className="flex gap-2 items-start header-style">
          ...
        </nav>
        <DarkModeToggleBtn />
      </div>
    </header>
  );
}

이제 다크모드에서는 별 버튼이 라이트모드에서는 해 모양의 버튼이 보인다.

tailwind로 dark: 로 다크모드에 대한 스타일을 주면 theme이 "dark" 일 때 해당 스타일을 적용한다.

// styles/globals.css

.bg-primary {
  @apply bg-white dark:bg-slate-900;
}