
tailwind를 이용 하여 디자인을 적용 해보자
import React, { useEffect, useState } from "react";
import { NavLink } from "react-router-dom";
const menu = [
{
label: "📊 DASHBOARD",
path: "/"
},
{
label: "👥 Category2",
path: "/category2",
children: [
{ label: "page1", path: "/users/login" },
{ label: "", path: "/users/betting" },
{ label: "결제 분석", path: "/users/payment" },
{ label: "퍼널 분석", path: "/users/funnel" }
]
},
{
label: "📁 이벤트 로그",
path: "/events"
},
{
label: "⚙️ 시스템 설정",
path: "/system"
},
{
label: "🧠 고급 분석",
path: "/advanced"
}
];
export default function GNB() {
const [isDark, setIsDark] = useState(() => document.documentElement.classList.contains("dark"));
const toggleDark = () => {
const newVal = !isDark;
document.documentElement.classList.toggle("dark", newVal);
localStorage.setItem("theme", newVal ? "dark" : "light");
setIsDark(newVal);
};
useEffect(() => {
const saved = localStorage.getItem("theme");
if (saved === "dark") {
document.documentElement.classList.add("dark");
setIsDark(true);
}
}, []);
return (
<header className="relative z-50 flex items-center justify-between w-full h-16 px-8 text-gray-900 bg-white border-b border-gray-200 shadow dark:bg-gray-900 dark:border-gray-700 dark:text-white">
<nav className="flex items-center space-x-6">
<span className="text-lg font-bold tracking-tight">🎯 유저 분석툴</span>
{menu.map((item, idx) =>
item.children ? (
<div key={idx} className="relative group">
<span className="px-3 py-2 rounded cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800">{item.label}</span>
<div className="absolute top-full left-0 mt-1 bg-white dark:bg-gray-800 shadow-lg rounded border dark:border-gray-700 opacity-0 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto transition-opacity z-10 min-w-[160px]">
{item.children.map((child, i) => (
<NavLink key={i} to={child.path} className={({ isActive }) => `block px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-700 ${isActive ? "font-semibold" : ""}`}>
{child.label}
</NavLink>
))}
</div>
</div>
) : (
<NavLink key={idx} to={item.path} className={({ isActive }) => `px-3 py-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800 ${isActive ? "font-semibold" : ""}`}>
{item.label}
</NavLink>
)
)}
</nav>
<div className="flex items-center space-x-4 text-sm">
<button onClick={toggleDark} className="px-3 py-1 text-black bg-gray-200 rounded dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 dark:text-white">
{isDark ? "🌙 다크" : "☀️ 라이트"}
</button>
<span className="text-gray-500 dark:text-gray-300">👤 운영자</span>
<button className="px-3 py-1 text-white bg-red-500 rounded hover:bg-red-600">로그아웃</button>
</div>
</header>
);
}
import React from "react";
import GNB from "@/components/Navigations/GNB";
import Routes from "@/config/Routes";
import { BrowserRouter as Router } from "react-router-dom";
const App = () => {
return (
<div className="flex flex-row justify-center min-h-screen">
<div className="flex flex-col flex-1 ">
<Router>
<GNB />
<div className="flex flex-1 w-full text-black transition-colors duration-300 bg-white dark:bg-gray-900 dark:text-gray-100">
<Routes />
</div>
</Router>
</div>
</div>
);
};
export default App;
./src/components/Navigations/SideNavBar.tsx
import React from "react";
import { NavLink } from "react-router-dom";
const MenuData = [
{ label: "page1", path: "/category4/page1" },
{ label: "page2", path: "/category4/page2" },
{ label: "page3", path: "/category4/page3" },
{ label: "page4", path: "/category4/page4" }
];
export default function SideNavBar() {
return (
<aside className="w-48 border-r border-gray-200 dark:border-gray-700">
<nav className="">
{MenuData.map((item, idx) => (
<NavLink key={idx} to={item.path} className={({ isActive }) => `block px-3 py-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800 ${isActive ? "font-bold bg-gray-100 dark:bg-gray-800 dark:text-white" : ""}`}>
{item.label}
</NavLink>
))}
</nav>
</aside>
);
}
./src/pages/Category4/index.tsx
import React from "react";
import SideNavBar from "@/components/Navigations/SideNavBar";
import PageLayout from "@/components/PageLayout";
import { Outlet } from "react-router-dom";
const Category4 = () => {
return (
<PageLayout className="flex-row p-0">
<SideNavBar />
<Outlet />
</PageLayout>
);
};
export default Category4;
// tailwind.config.js
module.exports = {
darkMode: "class", // or "media"
content: [
"./src/**/*.{js,ts,jsx,tsx}", // 👈 필수
"./public/index.html"
],
theme: {
extend: {}
},
plugins: []
};
./src/styles/tailwind.css
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));