import { Check, CircleQuestionMark, CircleUser, Globe, Lock, Monitor, Moon, Server, Settings, Sun, Users, } from "lucide-react"; import { NavLink, unstable_useRoute as useRoute, useLocation, useSubmit } from "react-router"; import Link from "~/components/link"; import { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger } from "~/components/menu"; import logoBg from "~/logo/dark-bg.svg"; import logoDark from "~/logo/dark.svg"; import logoLight from "~/logo/light.svg"; import cn from "~/utils/cn"; import type { ColorScheme } from "~/utils/color-scheme"; export interface HeaderProps { user: { subject: string; name: string; email?: string; username?: string; picture?: string; }; access: { ui: boolean; machines: boolean; dns: boolean; users: boolean; policy: boolean; settings: boolean; }; configAvailable: boolean; } const tabs = [ { to: "/machines", icon: Server, label: "Machines", key: "machines" }, { to: "/users", icon: Users, label: "Users", key: "users" }, { to: "/acls", icon: Lock, label: "Access Control", key: "policy" }, { to: "/dns", icon: Globe, label: "DNS", key: "dns" }, { to: "/settings", icon: Settings, label: "Settings", key: "settings" }, ] as const; const colorSchemes = [ { value: "system", label: "System", icon: Monitor }, { value: "light", label: "Light", icon: Sun }, { value: "dark", label: "Dark", icon: Moon }, ] as const satisfies ReadonlyArray<{ value: ColorScheme; label: string; icon: typeof Monitor; }>; export default function Header({ user, access, configAvailable }: HeaderProps) { const submit = useSubmit(); const showTabs = access.ui; const rootRoute = useRoute("root"); const currentColorScheme: ColorScheme = rootRoute?.loaderData?.colorScheme ?? "system"; // useLocation returns the path with the basename already stripped, which is // what `redirect()` expects — react-router re-applies the basename when // following the redirect on the client. const location = useLocation(); const returnTo = location.pathname + location.search; return (
Headplane logo

headplane

{showTabs && ( )}
Docs Headscale Download {user.picture ? ( {user.name} ) : ( )}
{user.subject === "api_key" ? ( <>

API Key

{user.name}

) : ( <>

{user.name}

{user.email &&

{user.email}

} )}
{colorSchemes.map(({ value, label, icon: Icon }) => ( submit( { colorScheme: value, returnTo }, { action: "/api/color-scheme", method: "POST" }, ) } >
{label} {currentColorScheme === value && }
))} submit({}, { action: "/logout", method: "POST" })} > Logout
{showTabs && (
)}
); }