Next.js와 Typescript로 간단한 로그인 기능을 연습하면서 다크모드 기능을 함께 구현해보았다.
찾아보니 shadcn/ui
에서 제공하는 next-themes
로 쉽게 구현이 가능하다는 것을 알게되었다.
Next-themes
Next.js 의 app router + Typescript + tailwindCSS
먼저 next-themes
를 설치해주어야 한다.
npm install next-themes
yarn add next-themes
참고
공식문서
이대로 보고 따라하면 큰 문제없이 구현할 수 있다.
먼저 layout.tsx
파일이 csr이 아니기 때문에 따로 provider.tsx
파일을 만들어주었다.
// provider.tsx
"use client";
import React from "react";
import { ModeToggle } from "@/components/mode-toggle";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes/dist/types";
export const ThemeProvider = ({ children, ...props }: ThemeProviderProps) => {
return (
<NextThemesProvider {...props} attribute="class" defaultTheme="system">
{children}
// 모드선택 토글버튼
<ModeToggle className={"absolute top-6 right-6"} />
</NextThemesProvider>
);
};
여기서 defaultTheme
은 처음 고정값을 어떻게 설정할지에 대한 것인데 처음에는 light로 설정했다가 그냥 시스템설정을 따르는 것으로 바꾸었다.
그리고 attribute
는 tailwndCSS의 클래스로 다크모드를 설정하기 위해 class로 설정해주었다.
// tailwind.config.ts
const config = {
darkMode: ["class"],
// ...생략
그리고 다크모드, 라이트모드를 선택할 수 있는 토글버튼 파일을 만들어주었다.
// mode-toggle.tsx
import { Moon, Sun } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { useTheme } from "next-themes";
export function ModeToggle({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
const { setTheme } = useTheme();
return (
<div className={className} {...props}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<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" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>
Light
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
}
shadcn/ui
에서 제공해주는 dropdown-menu
와 button
도 다운받아 주어야 하는데 방법은 앞에 작성한 글을 참고해도 좋을 것 같다!
보러가기
마지막으로 최상위 파일인 layout.tsx
에 추가해주면 된다!
// ... 생략
return (
<html lang="en">
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
라이트모드
다크모드
아직 화면은 구현되지 않았지만 이렇게 모드변경이 가능하다!
공식문서 보는것이 어렵게 느껴지기도 하지만 정말 상세하게 잘 되어있다고 생각한다. 그렇기 때문에 조금만 꼼꼼히 살펴보고 사용해보면 다양한 기능을 구현할 수 있다는 것이 신기하고 재미있다.
더 살펴봐야겠다!