CI / verify (push) Failing after 5m9s
Align the notebook browser with the physical LCD, refresh real project captures and navigation, simplify service content, and stabilize hero hydration.
137 lines
5.3 KiB
TypeScript
137 lines
5.3 KiB
TypeScript
"use client";
|
|
|
|
import { type KeyboardEvent, useRef, useState } from "react";
|
|
import {
|
|
CV_DOWNLOAD_NAME,
|
|
CV_URL,
|
|
NAVIGATION_ITEMS,
|
|
} from "@/lib/site-navigation";
|
|
import MagneticButton from "./cinematic/MagneticButton";
|
|
import { Logo } from "./Logo";
|
|
|
|
const MENU_ID = "site-navigation-menu";
|
|
|
|
export function Header() {
|
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
const menuButtonRef = useRef<HTMLButtonElement>(null);
|
|
|
|
const closeMobileMenu = () => setMobileMenuOpen(false);
|
|
|
|
const handleMenuKeyDown = (event: KeyboardEvent<HTMLElement>) => {
|
|
if (event.key !== "Escape") return;
|
|
|
|
event.preventDefault();
|
|
closeMobileMenu();
|
|
menuButtonRef.current?.focus();
|
|
};
|
|
|
|
return (
|
|
<header className="ds-section-dark fixed inset-x-0 top-0 z-[9000] h-[52px] w-full border-b border-[rgba(255,255,255,0.06)] bg-[var(--ink)]/95 px-sp-8 backdrop-blur-xl lg:px-sp-16">
|
|
<div className="ds-section-shell flex h-full items-center justify-between">
|
|
<a href="/#home" className="flex items-center gap-3 no-underline">
|
|
<Logo variant="mark" size="sm" theme="dark" className="shrink-0" />
|
|
<span className="font-display text-sm font-extrabold tracking-tight text-white">
|
|
evandro<span className="text-[var(--slash)]">.dev.br</span>
|
|
</span>
|
|
</a>
|
|
|
|
<nav
|
|
aria-label="Navegação principal"
|
|
className="site-header-nav items-center"
|
|
>
|
|
<ul className="flex list-none items-center gap-sp-2">
|
|
{NAVIGATION_ITEMS.map((item) => (
|
|
<li key={item.href}>
|
|
<MagneticButton
|
|
as="a"
|
|
href={item.href}
|
|
className="ds-link rounded-sm px-sp-3 py-sp-2 text-white/85 transition-colors hover:bg-white/10 hover:text-white"
|
|
strength={0.15}
|
|
>
|
|
{item.label}
|
|
</MagneticButton>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</nav>
|
|
|
|
<div className="flex items-center gap-sp-4">
|
|
<MagneticButton
|
|
as="a"
|
|
href={CV_URL}
|
|
download={CV_DOWNLOAD_NAME}
|
|
className="site-header-cv ds-link ds-link-accent rounded-sm font-semibold transition-shadow hover:shadow-[0_0_0_1px_rgba(232,255,0,.8),0_8px_24px_rgba(232,255,0,.35)]"
|
|
strength={0.2}
|
|
>
|
|
Download CV
|
|
</MagneticButton>
|
|
<button
|
|
ref={menuButtonRef}
|
|
type="button"
|
|
className="site-header-menu-toggle flex h-11 w-11 flex-col items-center justify-center gap-sp-2 border-none bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--slash)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--ink)]"
|
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
|
aria-controls={mobileMenuOpen ? MENU_ID : undefined}
|
|
aria-label={mobileMenuOpen ? "Fechar menu" : "Abrir menu"}
|
|
aria-expanded={mobileMenuOpen}
|
|
onKeyDown={handleMenuKeyDown}
|
|
>
|
|
<span
|
|
className={`h-0.5 w-5 bg-white transition-transform duration-300 ${mobileMenuOpen ? "translate-y-[6px] rotate-45" : ""}`}
|
|
/>
|
|
<span
|
|
className={`h-0.5 w-5 bg-white transition-opacity duration-300 ${mobileMenuOpen ? "opacity-0" : ""}`}
|
|
/>
|
|
<span
|
|
className={`h-0.5 w-5 bg-white transition-transform duration-300 ${mobileMenuOpen ? "-translate-y-[6px] -rotate-45" : ""}`}
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{mobileMenuOpen ? (
|
|
<div className="site-header-mobile-panel absolute inset-x-0 top-[52px] border-b border-[rgba(255,255,255,0.06)] bg-[var(--ink)]/98 px-sp-6 backdrop-blur-xl lg:px-sp-16">
|
|
<div className="ds-section-shell flex flex-col py-sp-6">
|
|
<nav
|
|
id={MENU_ID}
|
|
aria-hidden={!mobileMenuOpen}
|
|
aria-label="Navegação mobile"
|
|
onKeyDown={handleMenuKeyDown}
|
|
>
|
|
<ul className="flex list-none flex-col gap-sp-2">
|
|
{NAVIGATION_ITEMS.map((item) => (
|
|
<li key={item.href}>
|
|
<MagneticButton
|
|
as="a"
|
|
href={item.href}
|
|
className="ds-link block rounded-sm py-sp-3 text-white/85 transition-[padding,color] hover:pl-sp-2 hover:text-white"
|
|
onClick={closeMobileMenu}
|
|
strength={0.15}
|
|
>
|
|
{item.label}
|
|
</MagneticButton>
|
|
</li>
|
|
))}
|
|
<li>
|
|
<MagneticButton
|
|
as="a"
|
|
href={CV_URL}
|
|
download={CV_DOWNLOAD_NAME}
|
|
className="ds-link ds-link-accent mt-sp-2 inline-flex rounded-sm font-semibold"
|
|
onClick={() => {
|
|
closeMobileMenu();
|
|
menuButtonRef.current?.focus();
|
|
}}
|
|
strength={0.15}
|
|
>
|
|
Download CV
|
|
</MagneticButton>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
) : null}
|
|
</header>
|
|
);
|
|
}
|