diff --git a/app/components/Navbar.tsx b/app/components/Navbar.tsx index 1423f87..456833d 100644 --- a/app/components/Navbar.tsx +++ b/app/components/Navbar.tsx @@ -1,5 +1,6 @@ import Link from 'next/link'; import LogoutButton from './LogoutButton'; +import ThemeToggle from './ThemeToggle'; import { GraduationCap, User, Hexagon } from 'lucide-react'; interface NavLink { href: string; label: string; } @@ -43,6 +44,7 @@ export default function Navbar({ username, role, links }: Props) { {username} )} + diff --git a/app/components/ThemeToggle.tsx b/app/components/ThemeToggle.tsx new file mode 100644 index 0000000..3f4d29c --- /dev/null +++ b/app/components/ThemeToggle.tsx @@ -0,0 +1,35 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { Sun, Moon } from 'lucide-react'; + +export default function ThemeToggle() { + const [theme, setTheme] = useState<'dark' | 'light'>('dark'); + + useEffect(() => { + const saved = localStorage.getItem('theme') as 'dark' | 'light' | null; + // Default to system preference if no saved choice + const system = window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'; + const initial = saved ?? system; + setTheme(initial); + document.documentElement.setAttribute('data-theme', initial); + }, []); + + function toggle() { + const next = theme === 'dark' ? 'light' : 'dark'; + setTheme(next); + document.documentElement.setAttribute('data-theme', next); + localStorage.setItem('theme', next); + } + + return ( + + ); +} diff --git a/app/globals.css b/app/globals.css index 8ad4658..526699e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -5,7 +5,6 @@ --bg2: #0c0f14; --bg3: #111520; --bg4: #161b28; - --bg5: #ababab; --border: rgba(255,255,255,0.06); --border2: rgba(255,255,255,0.1); --accent: #6366f1; @@ -25,6 +24,28 @@ --radius-lg:14px; } +/* ── Light (cream) theme ── */ +[data-theme="light"] { + --bg: #f5f0e8; + --bg2: #faf7f2; + --bg3: #ede8df; + --bg4: #e4ddd2; + --border: rgba(0,0,0,0.08); + --border2: rgba(0,0,0,0.14); + --accent: #4f46e5; + --accent2: #6366f1; + --accent3: #4338ca; + --glow: rgba(99,102,241,0.15); + --glow2: rgba(99,102,241,0.06); + --green: #059669; + --red: #dc2626; + --orange: #d97706; + --text: #1c1917; + --text2: #44403c; + --text3: #78716c; + --text4: #a8a29e; +} + html { height: 100%; } body { min-height: 100%; @@ -74,6 +95,9 @@ a:hover { color: var(--text); } -webkit-backdrop-filter: blur(20px) saturate(180%); border-bottom: 1px solid var(--border); } +[data-theme="light"] .navbar { + background: rgba(245,240,232,0.9); +} .navbar-inner { display: flex; align-items: center; @@ -456,6 +480,13 @@ tbody tr:hover td { color: var(--text); } 0 24px 64px rgba(0,0,0,0.6), 0 0 80px rgba(99,102,241,0.06); } +[data-theme="light"] .login-card { + background: var(--bg2); + box-shadow: 0 0 0 1px var(--border2), 0 24px 64px rgba(0,0,0,0.12); +} +[data-theme="light"] .login-page::before { + background: radial-gradient(ellipse, rgba(99,102,241,0.06) 0%, transparent 65%); +} .login-logo { text-align: center; margin-bottom: 2.25rem; } .login-logo-icon { display: flex; justify-content: center; margin-bottom: 0.75rem; } .login-logo-title { diff --git a/app/layout.tsx b/app/layout.tsx index dbe3dfb..7fc20ab 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -14,10 +14,20 @@ export const metadata: Metadata = { export default function RootLayout({ children }: { children: React.ReactNode }) { return ( + + {/* Prevent flash of wrong theme */} +