diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index 9531db03..4335d293 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -6,6 +6,7 @@ import type { ReactNode } from "react"; import { AdminHubChrome } from "@/components/admin/admin-hub-chrome"; import { AdminMobileWrapper } from "@/components/admin/admin-mobile-wrapper"; import { AdminNavLink } from "@/components/admin/admin-nav-link"; +import { ThemeSwitcher } from "@/components/theme-switcher"; import { requireStaff } from "@/lib/admin/guard"; import { ADMIN_NAV_GROUPS } from "@/lib/admin-nav"; import { prisma } from "@/lib/prisma"; @@ -73,6 +74,7 @@ async function Sidebar({ {t("rankLabel", { rank: staff.rank })} + @@ -141,6 +143,7 @@ async function Topbar({ + {staff.username} diff --git a/src/components/theme-switcher.tsx b/src/components/theme-switcher.tsx index 0d8c17d7..7d335ae7 100644 --- a/src/components/theme-switcher.tsx +++ b/src/components/theme-switcher.tsx @@ -1,13 +1,18 @@ "use client"; +import { Moon, Sun } from "lucide-react"; import { useEffect, useState } from "react"; /** * Light/dark toggle. The class lives on ; theme-init.js applies the * saved choice before paint. We sync React state after mount so SSR hydration - * does not desync from the real DOM class (which forced a double-click before). + * does not desync from the real DOM class. */ -export function ThemeSwitcher() { +export function ThemeSwitcher({ + variant = "nav", +}: { + variant?: "nav" | "admin"; +}) { const [dark, setDark] = useState(false); const [ready, setReady] = useState(false); @@ -27,13 +32,32 @@ export function ThemeSwitcher() { } } + const label = dark ? "Switch to light mode" : "Switch to dark mode"; + const title = dark ? "Light mode" : "Dark mode"; + + if (variant === "admin") { + return ( + + {dark ? : } + + ); + } + return (