import { Dialog } from "@base-ui/react/dialog"; import { useSearchContext } from "fumadocs-ui/contexts/search"; import { Monitor, Moon, Search, Sun } from "lucide-react"; import { useTheme } from "next-themes"; import { Fragment, type ReactNode, useSyncExternalStore } from "react"; import { Link, useLocation } from "react-router"; import LogoMark from "@/components/logo-mark"; import VersionPicker from "@/components/version-picker"; export const iconButtonClass = "text-muted hover:bg-hover hover:text-fg inline-flex size-8 shrink-0 items-center justify-center rounded-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent [&_svg]:size-4"; const themeOptionClass = "focus-visible:outline-accent inline-flex size-6 items-center justify-center rounded-[4px] focus-visible:outline-2 [&_svg]:size-3.5"; const themeList = [ { value: "light", label: "Light", Icon: Sun }, { value: "dark", label: "Dark", Icon: Moon }, { value: "system", label: "System", Icon: Monitor }, ]; const links = [ { to: "/introduction", label: "Docs" }, { to: "/changelog", label: "Changelog" }, ]; export default function Header({ menu }: { menu?: ReactNode }) { const { pathname } = useLocation(); const isChangelog = pathname.startsWith("/changelog"); return (
headplane
{menu}
); } function ThemePicker() { const { theme, setTheme } = useTheme(); // The stored choice only exists in the browser, so prerendered HTML shows none selected. const isMounted = useSyncExternalStore( () => () => {}, () => true, () => false, ); // Until a choice is stored, the theme follows the system, the last option. const storedIndex = isMounted ? themeList.findIndex((item) => item.value === theme) : -1; const currentIndex = storedIndex === -1 ? themeList.length - 1 : storedIndex; const current = themeList[currentIndex]; const next = themeList[(currentIndex + 1) % themeList.length]; return ( <>
{themeList.map(({ value, label, Icon }) => { const isActive = isMounted && theme === value; return ( ); })}
); } function SearchButton() { const { enabled, hotKey, dialogHandle } = useSearchContext(); if (!enabled) { return null; } return ( <> Search docs {hotKey.map((key, index) => ( {key.display} ))} ); } function GitHubIcon() { return ( ); }