feat(home): posicionamento com prova, menu sem recarregar e WhatsApp em todo o site
H1 'Sites e sistemas que trazem pedidos pelo WhatsApp e tiram sua operação da planilha.'; HeroWork maior com a SEV; menu Cases, Serviços, Como trabalho, Sobre e IA com next/link e pré-carregamento no hover; menu do celular em tela cheia; WhatsApp flutuante e no rodapé com a mensagem da rota; rodapé em todas as páginas; FAQ da home; /ia como oferta de revisão de app feito com IA; formulário com noscript, validação do mailto e plano B do pop-up; cartões sem foco indevido; sem a fonte Monument.
This commit is contained in:
1 parent
e80f73d075
commit
10f170abf4
56 files changed
+3099
-906
No files matched your search
+82
-33
@@ -1,13 +1,66 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { type KeyboardEvent, useEffect, useRef, useState } from "react";
|
||||
import { NAVIGATION_ITEMS } from "@/lib/site-navigation";
|
||||
import MagneticButton from "./cinematic/MagneticButton";
|
||||
import {
|
||||
isServiceOrCasePath,
|
||||
type WhatsAppContexts,
|
||||
whatsAppSubjectForPath,
|
||||
} from "@/lib/whatsapp";
|
||||
import HoverPrefetchLink from "./HoverPrefetchLink";
|
||||
import { Logo } from "./Logo";
|
||||
import WhatsAppLink from "./WhatsAppLink";
|
||||
|
||||
const MENU_ID = "site-navigation-menu";
|
||||
const CTA_LABEL = "Falar sobre meu projeto";
|
||||
|
||||
export function Header() {
|
||||
/**
|
||||
* Botão de contato do cabeçalho. Nas páginas de serviço e de case ele abre o WhatsApp já com o assunto da página;
|
||||
* nas demais leva ao formulário da home.
|
||||
*/
|
||||
function ContactCta({
|
||||
className,
|
||||
placement,
|
||||
viaWhatsApp,
|
||||
subject,
|
||||
onNavigate,
|
||||
}: {
|
||||
className: string;
|
||||
placement: string;
|
||||
viaWhatsApp: boolean;
|
||||
subject?: string;
|
||||
onNavigate?: () => void;
|
||||
}) {
|
||||
if (viaWhatsApp) {
|
||||
return (
|
||||
<WhatsAppLink
|
||||
className={className}
|
||||
service={subject}
|
||||
placement={placement}
|
||||
onClick={onNavigate}
|
||||
>
|
||||
{CTA_LABEL}
|
||||
</WhatsAppLink>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Link href="/#contact" className={className} onClick={onNavigate}>
|
||||
{CTA_LABEL}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export function Header({
|
||||
whatsAppContexts,
|
||||
}: {
|
||||
/** Nomes dos serviços e dos cases, montados no servidor (app/layout.tsx), para o WhatsApp falar da página aberta. */
|
||||
whatsAppContexts?: WhatsAppContexts;
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
const viaWhatsApp = isServiceOrCasePath(pathname);
|
||||
const subject = whatsAppSubjectForPath(pathname, whatsAppContexts);
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const menuButtonRef = useRef<HTMLButtonElement>(null);
|
||||
@@ -45,13 +98,13 @@ export function Header() {
|
||||
}`}
|
||||
>
|
||||
<div className="ds-section-shell flex h-full items-center justify-between gap-sp-6">
|
||||
<a
|
||||
<HoverPrefetchLink
|
||||
href="/#home"
|
||||
aria-label="Evandro.dev.br — início"
|
||||
className="flex min-h-11 shrink-0 items-center no-underline"
|
||||
>
|
||||
<Logo theme="dark" loading="eager" className="w-40 sm:w-44" />
|
||||
</a>
|
||||
</HoverPrefetchLink>
|
||||
|
||||
<nav
|
||||
aria-label="Navegação principal"
|
||||
@@ -60,12 +113,12 @@ export function Header() {
|
||||
<ul className="flex list-none items-center gap-sp-4">
|
||||
{NAVIGATION_ITEMS.map((item) => (
|
||||
<li key={item.href}>
|
||||
<a
|
||||
<HoverPrefetchLink
|
||||
href={item.href}
|
||||
className="inline-flex min-h-11 items-center whitespace-nowrap rounded-sm px-sp-3 font-display text-sm font-medium normal-case tracking-normal text-white/80 no-underline transition-colors hover:bg-white/5 hover:text-white"
|
||||
>
|
||||
{item.label}
|
||||
</a>
|
||||
</HoverPrefetchLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -73,12 +126,12 @@ export function Header() {
|
||||
|
||||
<div className="flex shrink-0 items-center">
|
||||
<div className="hidden xl:block">
|
||||
<a
|
||||
href="/#contact"
|
||||
<ContactCta
|
||||
className="inline-flex min-h-11 items-center whitespace-nowrap rounded-sm bg-[var(--slash)] px-sp-4 font-display text-sm font-semibold normal-case tracking-normal text-[var(--ink)] no-underline transition-colors hover:bg-[var(--white)]"
|
||||
>
|
||||
Falar sobre meu projeto
|
||||
</a>
|
||||
placement="header"
|
||||
viaWhatsApp={viaWhatsApp}
|
||||
subject={subject}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
ref={menuButtonRef}
|
||||
@@ -104,41 +157,37 @@ export function Header() {
|
||||
</div>
|
||||
|
||||
{mobileMenuOpen ? (
|
||||
<div className="absolute inset-x-0 top-[var(--site-header-height)] max-h-[calc(100dvh-var(--site-header-height))] overflow-y-auto border-b border-white/12 bg-[var(--ink)] px-sp-6 lg:px-sp-8 xl:hidden">
|
||||
<div className="ds-section-shell flex flex-col py-sp-6">
|
||||
// Tela cheia abaixo da barra, com fundo opaco: o conteúdo da página não aparece por trás dos links.
|
||||
<div className="absolute inset-x-0 top-[var(--site-header-height)] flex h-[calc(100dvh-var(--site-header-height))] flex-col overflow-y-auto overscroll-contain bg-[var(--ink)] px-sp-6 pb-[calc(var(--sp-6)+env(safe-area-inset-bottom))] lg:px-sp-8 xl:hidden">
|
||||
<div className="ds-section-shell flex flex-1 flex-col">
|
||||
<nav
|
||||
id={MENU_ID}
|
||||
aria-hidden={!mobileMenuOpen}
|
||||
aria-label="Navegação mobile"
|
||||
className="flex flex-1 flex-col"
|
||||
onKeyDown={handleMenuKeyDown}
|
||||
>
|
||||
<ul className="flex list-none flex-col gap-sp-2">
|
||||
<ul className="flex list-none flex-col">
|
||||
{NAVIGATION_ITEMS.map((item) => (
|
||||
<li key={item.href}>
|
||||
<MagneticButton
|
||||
as="a"
|
||||
strength={0}
|
||||
wrapperClassName="w-full"
|
||||
<li key={item.href} className="border-b border-white/10">
|
||||
<HoverPrefetchLink
|
||||
href={item.href}
|
||||
className="flex min-h-11 items-center rounded-sm px-sp-3 py-sp-3 font-display text-sm font-medium normal-case tracking-normal text-white/80 no-underline transition-colors hover:bg-white/5 hover:text-white"
|
||||
className="flex min-h-14 items-center font-display text-[22px] font-medium normal-case leading-tight tracking-normal text-white/85 no-underline transition-colors hover:text-white"
|
||||
onClick={closeMobileMenu}
|
||||
>
|
||||
{item.label}
|
||||
</MagneticButton>
|
||||
</HoverPrefetchLink>
|
||||
</li>
|
||||
))}
|
||||
<li>
|
||||
<MagneticButton
|
||||
as="a"
|
||||
strength={0}
|
||||
href="/#contact"
|
||||
className="mt-sp-4 inline-flex min-h-11 items-center rounded-sm bg-[var(--slash)] px-sp-4 font-display text-sm font-semibold normal-case tracking-normal text-[var(--ink)] no-underline transition-colors hover:bg-[var(--white)]"
|
||||
onClick={closeMobileMenu}
|
||||
>
|
||||
Falar sobre meu projeto
|
||||
</MagneticButton>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="mt-auto pt-sp-8">
|
||||
<ContactCta
|
||||
className="flex min-h-14 w-full items-center justify-center rounded-sm bg-[var(--slash)] px-sp-4 font-display text-[18px] font-semibold normal-case tracking-normal text-[var(--ink)] no-underline transition-colors hover:bg-[var(--white)]"
|
||||
placement="header_menu"
|
||||
viaWhatsApp={viaWhatsApp}
|
||||
subject={subject}
|
||||
onNavigate={closeMobileMenu}
|
||||
/>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user