/** * Sticky top bar, landing-parity: logo + site name + "Docs" badge, then the SAME * link row as the landing page's nav (section anchors on the landing home, blog, * docs) with the same sliding hover pill — so the two sites link into each other * seamlessly. Section/blog links are plain anchors into the landing SPA one level * up; "Docs" routes to this site's own root. The right side keeps the language * and theme toggles, GitHub, and — on small screens — the sidebar toggle. */ import { useRef } from "react"; import type { MouseEvent } from "react"; import { Link } from "react-router"; import { S } from "../lib/strings"; import { REPO_URL, SITE_URL } from "../lib/links"; import { GitHubIcon, MenuIcon, XIcon } from "./icons"; import { ThemeToggle } from "./theme-toggle"; import { LangToggle } from "./lang-toggle"; const SECTION_IDS = ["highlights", "quickstart", "benchmark", "contract", "features"] as const; export function Nav({ menuOpen, onToggleMenu }: { menuOpen: boolean; onToggleMenu: () => void }) { const pillRef = useRef(null); const pillVisible = useRef(false); const sectionLabel: Record<(typeof SECTION_IDS)[number], string> = { highlights: S.nav.highlights, quickstart: S.nav.quickstart, benchmark: S.nav.benchmark, contract: S.nav.contract, features: S.nav.features, }; const linkCls = "relative z-10 rounded-md px-2.5 py-1.5 text-sm text-gray-600 transition-colors hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100"; // Landing-parity active style: on the docs site, the "Docs" link is the current page. const activeLinkCls = "relative z-10 rounded-md px-2.5 py-1.5 text-sm transition-colors bg-black text-white hover:bg-black hover:text-white dark:bg-black dark:text-white dark:ring-1 dark:ring-gray-600 dark:hover:bg-black dark:hover:text-white"; /** * The hover pill appears IN PLACE under the first link it lands on (position * jumps with only the fade animating), slides while moving between links, and * fades out where it is on leave — never sweeping in from the nav's edge. */ const slideTo = (e: MouseEvent) => { const el = e.currentTarget; const pill = pillRef.current; if (!pill) return; if (!pillVisible.current) { pill.style.transitionProperty = "opacity"; pill.style.left = `${el.offsetLeft}px`; pill.style.width = `${el.offsetWidth}px`; void pill.offsetWidth; // flush the jump before restoring the full transition pill.style.transitionProperty = ""; pillVisible.current = true; } else { pill.style.left = `${el.offsetLeft}px`; pill.style.width = `${el.offsetWidth}px`; } pill.style.opacity = "1"; }; const hidePill = () => { const pill = pillRef.current; if (pill) pill.style.opacity = "0"; pillVisible.current = false; }; return (
{S.siteName} {S.docsBadge}
); }