feat: control room hero, SEO/AEO optimization and design system fixes
Hero: replace particle field with cobe globe (Capricorn view, multi-axis drag, reduced-motion safe), telemetry HUD with pointer parallax, particle text build effect, Space Grotesk display font. SEO: short titles with template, PT-BR accents, twitter cards on dynamic cases, escaped JSON-LD via lib/jsonld.ts, CSP report-only, 25 service FAQs answer-first. Design: fix TW4 layered reset killing spacing utilities, literal @theme tokens, mobile hero overflow, header overlap, empty case cards. Remove framer-motion (unified on motion/react), header version badge, phone number from hero CTA. Production build verified (24 static pages).
This commit is contained in:
1 parent
0920370f30
commit
b791b7de9e
94 files changed
+2621
-2889
No files matched your search
+69
-50
@@ -1,35 +1,48 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Logo } from "./Logo";
|
||||
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 navItems = [
|
||||
{ href: "#home", label: "Home" },
|
||||
{ href: "#about", label: "Sobre" },
|
||||
{ href: "#skills", label: "Habilidades" },
|
||||
{ href: "#experience", label: "Experiencia" },
|
||||
{ href: "#projects", label: "Projetos" },
|
||||
{ href: "#modalities", label: "Contratacao" },
|
||||
{ href: "#contact", label: "Contato" },
|
||||
];
|
||||
const MENU_ID = "site-navigation-menu";
|
||||
|
||||
export function Header() {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const menuButtonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const closeMobileMenu = () => {
|
||||
setMobileMenuOpen(false);
|
||||
menuButtonRef.current?.focus();
|
||||
};
|
||||
|
||||
const handleMenuKeyDown = (event: KeyboardEvent<HTMLElement>) => {
|
||||
if (event.key !== "Escape") return;
|
||||
|
||||
event.preventDefault();
|
||||
closeMobileMenu();
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="ds-section-dark fixed inset-x-0 top-0 z-50 h-[52px] w-full border-b border-[rgba(255,255,255,0.06)] bg-[var(--ink)]/95 px-sp-6 backdrop-blur-xl lg:px-sp-16">
|
||||
<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">
|
||||
<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 className="hidden items-center lg:flex">
|
||||
<nav
|
||||
aria-label="Navegação principal"
|
||||
className="site-header-nav items-center"
|
||||
>
|
||||
<ul className="flex list-none items-center gap-sp-2">
|
||||
{navItems.map((item) => (
|
||||
{NAVIGATION_ITEMS.map((item) => (
|
||||
<li key={item.href}>
|
||||
<MagneticButton
|
||||
as="a"
|
||||
@@ -45,24 +58,24 @@ export function Header() {
|
||||
</nav>
|
||||
|
||||
<div className="flex items-center gap-sp-4">
|
||||
<span className="ds-metric hidden rounded-full border border-white/10 px-[10px] py-1 text-white/40 lg:inline-flex">
|
||||
v1.0 / 2026
|
||||
</span>
|
||||
<MagneticButton
|
||||
as="a"
|
||||
href="/Profile.pdf"
|
||||
download="Evandro_Fonseca_Junior_CV.pdf"
|
||||
className="ds-link ds-link-accent hidden 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)] lg:inline-flex"
|
||||
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="flex h-8 w-8 flex-col items-center justify-center gap-sp-2 border-none bg-transparent lg:hidden"
|
||||
className="site-header-menu-toggle flex h-8 w-8 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-label="Menu"
|
||||
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" : ""}`}
|
||||
@@ -77,40 +90,46 @@ export function Header() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`absolute inset-x-0 top-[52px] overflow-hidden border-b border-[rgba(255,255,255,0.06)] bg-[var(--ink)]/98 px-sp-6 backdrop-blur-xl transition-all duration-300 lg:hidden lg:px-sp-16 ${mobileMenuOpen ? "max-h-[420px] opacity-100" : "max-h-0 opacity-0"}`}
|
||||
>
|
||||
<div className="ds-section-shell flex flex-col py-sp-6">
|
||||
<nav className="mb-sp-6">
|
||||
<ul className="flex list-none flex-col gap-sp-2">
|
||||
{navItems.map((item) => (
|
||||
<li key={item.href}>
|
||||
{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={item.href}
|
||||
className="ds-link block rounded-sm py-sp-3 text-white/85 transition-all hover:pl-sp-2 hover:text-white"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
href={CV_URL}
|
||||
download={CV_DOWNLOAD_NAME}
|
||||
className="ds-link ds-link-accent mt-sp-2 inline-flex rounded-sm font-semibold"
|
||||
onClick={closeMobileMenu}
|
||||
strength={0.15}
|
||||
>
|
||||
{item.label}
|
||||
Download CV
|
||||
</MagneticButton>
|
||||
</li>
|
||||
))}
|
||||
<li>
|
||||
<MagneticButton
|
||||
as="a"
|
||||
href="/Profile.pdf"
|
||||
download="Evandro_Fonseca_Junior_CV.pdf"
|
||||
className="ds-link ds-link-accent mt-sp-2 inline-flex rounded-sm font-semibold"
|
||||
strength={0.15}
|
||||
>
|
||||
Download CV
|
||||
</MagneticButton>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user