agency-web/app/components/SiteHeader.tsx

105 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useEffect, useState } from "react";
import { SITE } from "../content";
const NAV = [
{ href: "#services", label: "Services" },
{ href: "#work", label: "Work" },
{ href: "#about", label: "About" },
{ href: "#faq", label: "FAQ" },
];
/** Masthead-style sticky header with a mono "ticker bug" logo. */
export default function SiteHeader() {
const [open, setOpen] = useState(false);
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 24);
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
// lock body + escape to close mobile nav
useEffect(() => {
document.body.style.overflow = open ? "hidden" : "";
const onKey = (e: KeyboardEvent) => e.key === "Escape" && setOpen(false);
window.addEventListener("keydown", onKey);
return () => {
window.removeEventListener("keydown", onKey);
document.body.style.overflow = "";
};
}, [open]);
return (
<header className={`masthead ${scrolled ? "is-scrolled" : ""}`}>
<div className="masthead__bar frame">
<a href="#main" className="logo" aria-label="Feedback Studios — home">
<span className="logo__bug" aria-hidden="true">
FS
</span>
<span className="logo__name">Feedback&nbsp;Studios</span>
<span className="logo__tag" aria-hidden="true">
EST. 26 · REV
</span>
</a>
<nav className="masthead__nav" aria-label="Primary">
<ul>
{NAV.map((n) => (
<li key={n.href}>
<a href={n.href}>{n.label}</a>
</li>
))}
</ul>
</nav>
<a
className="btn btn--accent masthead__cta"
href={SITE.booking}
data-cursor="Lets talk"
>
Get a growth audit
</a>
<button
className="masthead__burger"
aria-expanded={open}
aria-controls="mobile-nav"
onClick={() => setOpen((o) => !o)}
>
<span className="sr-only">{open ? "Close menu" : "Open menu"}</span>
<span className="masthead__burger-box" data-open={open} aria-hidden="true">
<i /><i /><i />
</span>
</button>
</div>
<div className="masthead__rule" aria-hidden="true" />
{/* mobile drawer */}
<div id="mobile-nav" className="drawer" data-open={open}>
<nav aria-label="Mobile">
<ul>
{NAV.map((n, i) => (
<li key={n.href} style={{ transitionDelay: `${i * 50 + 60}ms` }}>
<a href={n.href} onClick={() => setOpen(false)}>
<span className="drawer__idx">0{i + 1}</span>
{n.label}
</a>
</li>
))}
</ul>
</nav>
<a
className="btn btn--accent"
href={SITE.booking}
onClick={() => setOpen(false)}
>
Get a growth audit
</a>
</div>
</header>
);
}