[Next 13] Next js + Tailwind 다크모드

Hyuk·2023년 5월 2일

NextJS

목록 보기
1/3

📝 Next js + Tailwind 다크모드

기본적으로 next 13버전에서 tailwind가 설치가 되어있다는 가정(13.2버전 이후)

ezgif com-video-to-gif

설치 라이브러리

npm i next-themes react-icons

next-themes란? (공식홈페이지)

Next.js에서 쉽게 테마를 전환할 수 있도록 도와주는 패키지입니다.(시스템 테마로도 업데이트 가능)


폴더 구조

src
 ├── Providers.tsx
 └── layout.tsx
        └── components
		└── Elements
			└── DarkMode
				└── DarkMode.tsx

next 13으로 폴더구조는 위와 같습니다.


📌 Providers.tsx

"use client";

import { ThemeProvider } from "next-themes";

const Providers = ({ children }: { children: React.ReactNode }) => {
  return <ThemeProvider attribute="class">{children}</ThemeProvider>;
};

export default Providers

Providers.tsx는 테마 provider입니다.
위를 통해서 해당 children은 일관된 테마를 유지할수있습니다.
해당 프로젝트에는 layout에서 body안에 적용을 시킬예정입니다.
여기서 핵심은 "use client"를 넣어줘야합니다.
csr로 작동을 해야 ThemeProvider가 작동을 합니다.

👉 이때 attribute="class"를 추가해줌으로써 className에 dark와 light가 토글이 됩니다.


📌 layout.tsx

import "./globals.css";
import { Inter } from "next/font/google";
import Header from "./components/Headers/Header";
import Providers from "./Providers";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: {
                                    children: React.ReactNode;
                                    }) {
  return (
    <html lang="en" className={`transition duration-300 ${inter.className}`}>
<body className="flex flex-col min-h-screen">
<Providers>
<Header />
<main className="bg-white dark: bg-black">
{children}
</main>
</Providers>
</body>
</html>
);
}

다음은 layout.tsx파일입니다.- (참고블로그)[https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts]
이 파일은 next에서 해당 공통적으로 들어가는 요소들을 추가하는 파일입니다.
이전 버전으로 예시를 들면 _app.tsx / _document.tsx 가 있습니다.
여기서 핵심은 아래 코드부분입니다.

<Providers>
  <Header />
  <main className="bg-white dark: bg-black">
    {children}
</main>
</Providers>

이전에 Providers.tsx에서 만든 컴포넌트를 불러와서
테마를 적용시킬 범위까지 감싸줍니다.
현 프로젝트는 tailwind이기때문에 이후 main처럼 className에 dark모드 부분에서 사용될 부분에만
위 코드처럼넣어줍니다.


📌 DarkMode.tsx

"use client";

import { BsFillSunFill, BsFillMoonFill } from "react-icons/bs";
import { useState, useEffect } from "react";
import { useTheme } from "next-themes";

interface IDarkMode {}

function DarkMode({}: IDarkMode) {
  const [mounted, setMounted] = useState(false);
  const { systemTheme, theme, setTheme } = useTheme();

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    return null;
  }

  const onClick = (mode: string) => () => {
    setTheme(mode);
  };

  const currentTheme = theme === "system" ? systemTheme : theme;

  return (
    <div className="bg-darkModeBg cursor-pointer rounded-[50%] p-1">
    {currentTheme === "dark" ? (
    <BsFillMoonFill onClick={onClick("light")} />
) : (
  <BsFillSunFill onClick={onClick("dark")} />
)}
  </div>
);
}

export default DarkMode;

핵심의 페이지 darkMode 버튼입니다.
마찬가지로 click이베트를 사용하기때문에 "use client"를 써줌으로 csr로 진행이 됩니다.

<div className="bg-darkModeBg cursor-pointer rounded-[50%] p-1">
  {currentTheme === "dark" ? (
   <BsFillMoonFill onClick={onClick("light")} />
) : (
  <BsFillSunFill onClick={onClick("dark")} />
)}
  </div>

추가적으로 아이콘을 통해서 다크모드와 라이트모드의 구별을 위해서 react-icons를 불러와서 jsx에 넣어줍니다.

이때 div에서 클래스네임중에 bg-darkModeBg은 무엇인가??
이거는 tailwind에서 사용자 설정을 해준 class입니다.
아래 tailwind설정에 보면 colors 안에 key값이 있습니다.

클래스안에 dark:를 써줘서 관리를 하는 방법이있고
위처럼 tailwind의 설정을 통해 css로 관리를 하는 방법 총 2가지 방법이있습니다.
더 좋은방법이 있다면 댓글 부탁드리겠습니다ㅎㅎ..

((공식 홈페이지))[https://github.com/pacocoursey/next-themes#readme]
위 useEffect 등 함수적인 부분은 next-Theme에 나와있는 내용을 그대로 카피한 부분이기때문에
따라만 해주신다면 문제가 없습니다.

📝 tailwind / css 설정

📌 tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: "class",
  theme: {
    extend: {
      colors: {
        darkModeBg: "var(--hello)",
      },
    }
  }
  ...
};

위에서 말한 tailwind class 설정방법입니다.


📌 global.css

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --foreground-rgb: 0, 0, 0;
  --background-start-rgb: 214, 219, 220;
  --background-end-rgb: 255, 255, 255;
  --hello: #aea;
}

:root.dark {
  --foreground-rgb: 255, 255, 255;
  --background-start-rgb: 0, 0, 0;
  --background-end-rgb: 0, 0, 0;
  --hello: #e5e5;
}

root.dark는 html에 class가 dark하고 light가 토글되어 나타납니다.
darkMode냐 lightMode냐에 따라서
root color를 통해서 tailwind 설정에서 var(--hello)를 통해 해당 칼라값을 찾아가고
그 해당값을 통해서 요소의 색상이 결정됩니다.

🤓 느낀점

모든것은 공식문서에 나타나있지만 아직은 서투르고 어려운 부분이 있다..!
어렵더라도 꾸준히 공식문서들을 활용하고 요령을 익히는 방법을 터득해보자!
profile
frontEnd Developer

0개의 댓글