Files
aibook-fun/marketing-site/components/Nav.jsx
T
pat 5eb257c987
deploy / build-and-deploy (push) Canceled after 0s
chore: brand presentation is AiBook.fun
2026-09-02 16:32:59 +00:00

103 lines
2.9 KiB
React

import { useEffect, useRef, useState } from "react";
import Link from "next/link";
const LINKS = [
{ href: "#recipe", label: "A recipe" },
{ href: "#letter", label: "Why" },
{ href: "#faq", label: "FAQ" },
];
function NavItem({ href, label, onClick }) {
if (href.startsWith("/")) {
return (
<Link href={href} onClick={onClick}>
{label}
</Link>
);
}
return (
<a href={href} onClick={onClick}>
{label}
</a>
);
}
export default function Nav() {
const [scrolled, setScrolled] = useState(false);
const [open, setOpen] = useState(false);
const navRef = useRef(null);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 12);
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
// While the mobile menu is open: close on Escape or an outside tap.
useEffect(() => {
if (!open) return;
const onKey = (e) => e.key === "Escape" && setOpen(false);
const onDown = (e) => {
if (navRef.current && !navRef.current.contains(e.target)) setOpen(false);
};
document.addEventListener("keydown", onKey);
document.addEventListener("pointerdown", onDown);
return () => {
document.removeEventListener("keydown", onKey);
document.removeEventListener("pointerdown", onDown);
};
}, [open]);
const close = () => setOpen(false);
return (
<nav ref={navRef} className={`nav${scrolled ? " scrolled" : ""}${open ? " open" : ""}`}>
<div className="nav-in">
<Link className="logo" href="/" onClick={close}>
AiBook<b>.</b>
<span className="dot">fun</span>
</Link>
<div className="nav-links">
{LINKS.map((l) => (
<NavItem key={l.href} href={l.href} label={l.label} />
))}
</div>
<div className="nav-actions">
<Link href="/read" className="btn btn-ghost nav-cta" onClick={close}>
Go to Library
</Link>
<a href="#get" className="btn btn-primary nav-cta">
Get the preview
</a>
</div>
<button
type="button"
className="nav-toggle"
aria-label={open ? "Close menu" : "Open menu"}
aria-expanded={open}
aria-controls="mobile-menu"
onClick={() => setOpen((v) => !v)}
>
<span className="bars" aria-hidden="true"></span>
</button>
</div>
<div className="nav-menu" id="mobile-menu">
{LINKS.map((l) => (
<NavItem key={l.href} href={l.href} label={l.label} onClick={close} />
))}
<Link href="/read" className="btn btn-ghost" onClick={close}>
Go to Library
</Link>
<a href="#get" className="btn btn-primary" onClick={close}>
Get the preview
</a>
</div>
</nav>
);
}