본문 바로가기
개발/React.JS, Next.JS

React.JS, Next.JS, shadcn/ui 에서 dark mode 설정하기

by GreatCoding 2023. 12. 20.

목표

React.JS와 Next.JS, shadcn/ui로 구성된 프로젝트에 dark mode를 적용하는 법을 알아보자.

 

다크모드 변경

Next.JS 프로젝트 셋팅

아래와 같은 create-next-app 명령어로 Next.JS 14버전의 새로운 프로젝트를 생성한다.

 

$ npx create-next-app@latest next-dark

 

명령어를 실행하면 사용자에게 몇가지 질문을 하는데 아래와 같이 src 디렉토리만 No를 선택하고,
Tailwind CSS, App Router는 사용하도록 Yes를 선택한다.

 

Need to install the following packages:
✔ Would you like to use TypeScript? … No / Yes > Yes
✔ Would you like to use ESLint? … No / Yes > Yes
✔ Would you like to use Tailwind CSS? … No / Yes > Yes
✔ Would you like to use `src/` directory? … No / Yes > No
✔ Would you like to use App Router? (recommended) … No / Yes > Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes > Yes
Creating a new Next.js

shadcn/ui 설치

설치가 완료되면 프로젝트 폴더로 이동 후 shadcn/ui를 설치하기위해 아래의 명령어를 입력한다

 

$ cd next-dark
$ npx shadcn-ui@latest init

 

타입스크립트를 사용하기 때문에 tailwind.config.js만 tailwind.config.ts로 변경하고, 테마는 Neutral을 사용하였다. 그외 나머지는 디폴트 옵션을 선택하면된다.

 

✔ Would you like to use TypeScript (recommended)? … no / yes > yes
✔ Which style would you like to use? > Default
✔ Which color would you like to use as base color? > Neutral
✔ Where is your global CSS file? … app/globals.css
✔ Would you like to use CSS variables for colors? … no / yes > yes
✔ Where is your tailwind.config.js located? … tailwind.config.ts
✔ Configure the import alias for components: … @/components
✔ Configure the import alias for utils: … @/lib/utils
✔ Are you using React Server Components? … no / yes > yes
✔ Write configuration to components.json. Proceed? … yes > yes

shadcn/ui button 설치

다크 모드 설정을 on/off로 토글하기 위해서 shacn/ui의 button 컴포넌트를 설치한다.

 

$ npx shadcn-ui@latest add button

 

다크모드 설정

next-themes 설치

다크모드 테마 설정을 위해 next-themes를 설치한다.

 

$ npm install next-themes

theme provider 생성

components/theme-provider.tsx 파일을 추가하여 아래의 코드를 추가한다.
참고 : 루트의 components 폴더는 shadcn/ui의 컴포넌트가 설치되는 경로다.

 

"use client"

import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

root layout에 provider 적용

위에서 작성한 ThemeProvider를 app/layout.tsx 에 적용하여 모든 하위 라우트 파일에 적용 받도록 한다.
(주의 : next-themes의 ThemeProvider가 아닌, 위에서 작성한 components폴더의 ThemeProvider를 import 해야한다.)

 

import "./globals.css";
import { ThemeProvider } from "@/components/theme-provider";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <ThemeProvider
          attribute="class"
          defaultTheme="system"
          enableSystem
          disableTransitionOnChange
        >
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

다크모드를 변경하는 토글 버튼 만들기

app/_components/dark-mode-toggle.tsx 파일을 새로 만들어 아래의 내용을 입력한다.
클라이언트에서만 렌더링 되는 버튼으로, dark mode와 light mode를 번갈아가면서 설정한다.

 

"use client";

import * as React from "react";
import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";

import { Button } from "@/components/ui/button";

export function DarkModeToggle() {
  const { resolvedTheme, setTheme } = useTheme();

  const toggleTheme = () => {
    if (resolvedTheme === "dark") {
      setTheme("light");
    } else {
      setTheme("dark");
    }
  };

  return (
    <Button variant="outline" size="icon" onClick={toggleTheme}>
      <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
      <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
    </Button>
  );
}

메인 페이지에 다크 모드 토글 버튼 추가

app/page.tsx 파일의 기존 내용을 아래의 내용으로 변경하여 버튼과 글자를 화면에 보여준다.

 

import { DarkModeToggle } from "./_components/dark-mode-toggle";

export default function Home() {
  return (
    <main className="flex flex-col items-center p-24">
      <DarkModeToggle />
      <div className="text-lg">다크모드 테스트</div>
    </main>
  );
}

최종 실행

아래의 명령어를 실행 후 웹브라우저에서 localhost:3000 주소로 접근하면 테마 버튼과 다크모드 테스트라는 글자를 볼 수 있다. 버튼을 눌러서 다크 모드와 라이트 모드로 테마가 잘 변경되는지 확인한다.

 

$ npm run dev

> next-dark@0.1.0 dev
> next dev

   ▲ Next.js 14.0.4
   - Local:        http://localhost:3000

 ✓ Ready in 2.4s
다크모드 변경

출처 : https://ui.shadcn.com/docs/dark-mode/next

댓글