개발/개발로그

[React] 간단한 성냥퍼즐 웹 서비스 만들기 3일차 (navbar, darkmode)

seungho-dev 2024. 11. 14. 19:30

귀없는 성냥이.png

오늘은 네비게이션바와 다크모드를 추가해보려고 한다.

 

개인적인 공부를 위해 작성하는 블로그입니다. 혹시라도 잘못되거나 부족한 부분이 있다면 댓글로 알려주시면 감사하겠습니다.

 


🔨 네이게이션바 만들기

우선 어제 라우팅을 조금 손봤는데 라우팅 설정이 많아지면서 main.js 만들었던 Router를 ./routes/index.jsx 로 분리하였다.

import * as React from 'react'
import * as ReactDOM from 'react-dom/client'
import Router from './routes/index'
import "./index.css"


ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <Router />
  </React.StrictMode>
)

 

components/Header.jsx를 다음과 같이 만들어 주고 root.jsx에 넣어주었다.

// src/components/Header.jsx

import { Link } from "react-router-dom";

export default function Header() {
  return (
    <header className="bg-white shadow-sm fixed w-full">
      <div className="container mx-auto px-4">
        <div className="flex justify-between h-16 items-center">
          <Link to="/" className="flex items-center">
            <img
              src="/logo2.webp"
              alt="Matchstick Puzzle"
              className="h-8 w-auto"
            />
            <span className="ml-2 text-xl font-bold text-gray-900">
              Matchstick
              Puzzle
            </span>
          </Link>
          
          <nav className="flex items-center space-x-4">
            <Link
              to="/"
              className="text-gray-600 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
            >
              퍼즐 목록
            </Link>
            <Link
              to="/account/profile"
              className="text-gray-600 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
            >
              로그인
            </Link>
          </nav>
        </div>
      </div>
    </header>
  );
}

// scr/routes/layouts/root.jsx

import { Outlet } from "react-router-dom"
import Header from "../../components/Header"

export default function Root() {
  return(
    <div className="min-h-screen bg-gray-50">
    <Header />
    <main className="container mx-auto px-4 py-8 pt-10">
      <Outlet />
    </main>
  </div>
  )
}

왼쪽에 어제 만든 귀없는 성냥이도 넣어주었다. react router 기능으로 Link 대신 NavLink를 사용하면 현재 위치한 라우팅을 체크하여 class에 active 값을 넣어주는데 이걸 활용하면 아래와 같이 활용가능하다. 나는 퍼즐이랑 로그인 페이지만 있으면 될 것 같아 다음에 필요하다면 써봐야겠다.

 

🌉 테일윈드 다크모드 설정

우선 tailwind.config.js 파일에 darkMode를 'class'로 설정해준다. 만약 사용자의 시스템 환경에 따라 다크모드를 바꾸려면 'media'로 설정하면 된다.

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}"
  ],
  darkMode: 'class',
  theme: {
    extend: {},
  },
  plugins: [],
}

 

그리고 Header.jsx에서 버튼을 만들고 눌렀을때 document.body의 클래스를 토글처리 되도록 해주면 테일윈드 속성으로 dark: 를 사용해 css를 설정할 수 있다. 

import { Link } from "react-router-dom";
import { useState } from "react";

export default function Header() {
  const [dark, setDark] = useState(false)

  const darkModeHandler = () => {
    setDark(!dark);
    document.body.classList.toggle("dark")
  }

  return (
    <header className="bg-white shadow-sm fixed w-full">
      <div className="container mx-auto px-4">
        <div className="flex justify-between h-16 items-center">
          <Link to="/" className="flex items-center">
            <img
              src="/logo2.webp"
              alt="Matchstick Puzzle"
              className="h-8 w-auto"
            />
            <span className="ml-2 text-xl font-bold text-gray-900">
              Matchstick
              Puzzle
            </span>
          </Link>
          
          <nav className="flex items-center space-x-4">
            <div>
              <button onClick={() => darkModeHandler()}>
                {dark ? "☀︎" : "☾"}
              </button>
            </div>
            <Link
              to="/"
              className="text-gray-600 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
            >
              퍼즐 목록
            </Link>
            <Link
              to="/account/profile"
              className="text-gray-600 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
            >
              로그인
            </Link>
          </nav>
        </div>
      </div>
    </header>
  );
}
import { Outlet, ScrollRestoration } from "react-router-dom"
import Header from "../../components/Header"

export default function Root() {
  return(
    <div className="min-h-screen bg-gray-50 dark:bg-slate-600">
    <Header />
    <main className="container mx-auto px-4 py-8 pt-10">
      <Outlet />
    </main>
    <ScrollRestoration />
  </div>
  )
}

 

완성!

 

내일부터는 드디어 퍼즐기능을 만들어봐야겠다!