터미널에
npx create-next-app@latest
√ What is your project named? ... new
√ Would you like to use TypeScript with this project? ... No / Yes
√ Would you like to use ESLint with this project? ... No / Yes
√ Would you like to use Tailwind CSS with this project? ... No / Yes
√ Would you like to use src/ directory with this project? ... No / Yes
√ Use App Router (recommended)? ... No / Yes
√ Would you like to customize the default import alias? ... No / Yes
이렇게 생성했다 NO/YES는 취향대로
후
npm i next-themes
npm i @heroicons/react
npm i react-icons
npm i next-themes @heroicons/react react-icons 이렇게 한번에 됨
/app/components/DarkModeBtn.tsx 에
"use client"
import { useState, useEffect } from "react"
import { useTheme } from "next-themes"
import { MoonIcon, SunIcon } from "@heroicons/react/24/solid"
const DarkModeBtn = () => {
const [mounted, setMounted] = useState(false)
const { systemTheme, theme, setTheme } = useTheme()
const [play, { stop }] = useSound("./sound/bubble-sound.mp3")
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) {
return null
}
const currentTheme = theme === "system" ? systemTheme : theme
return (
<div>
{currentTheme === "dark" ? (
<SunIcon
className="h-6 w-6 cursor-pointer text-yellow-400"
onClick={() => {
setTheme("light")
}}
/>
) : (
<MoonIcon
className="h-6 w-6 cursor-pointer text-slate-700"
onClick={() => {
setTheme("dark")
}}
/>
)}
</div>
)
}
export default DarkModeBtn
/app/components/Header.tsx 에
import DarkModeBtn from "./DarkModeBtn";
const Header = () => {
let user_name = "Shin";
return (
<header className="py-5 px-5 flex items-center justify-between">
<div>
<h4 className="font-popins font-normal text-xl">{user_name}</h4>
</div>
<div className="flex">
<DarkModeBtn />
<h4 className="ml-4">Login</h4>
</div>
</header>
);
};
export default Header;
app/Providers.tsx 에
"use client"
import { ThemeProvider } from "next-themes"
const Providers = ({ children }: { children: React.ReactNode }) => {
return (
<ThemeProvider enableSystem={true} attribute="class">
{children}
</ThemeProvider>
)
}
export default Providers
app/layout.tsx에
import "./globals.css";
import Header from "./components/Header";
import Providers from "./Providers";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html className="h-full scroll-smooth">
<head />
<body>
<Providers>
<Header />
<main>{children}</main>
</Providers>
</body>
</html>
);
}
/app/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;