Files
portifolio-evandrodevbr/app/components/Footer.tsx
T
evandro c7d09d63d4
CI / audit (push) Successful in 10m38s
CI / verify (push) Successful in 13m10s
CI / deploy (push) Successful in 1m50s
CI / e2e (push) Successful in 18m48s
feat(site): blocos 3D da marca, novas ofertas e hero mais abrangente
Hero e movimento
- cena 3D em tempo real com os blocos da marca (kit feito no Blender, 3d/blocos.py):
  marca, tela, integrações e dados; segue a rolagem, tem vida em repouso, reage ao
  cursor e, parada no topo, passa sozinha pelos estados com legenda
- três níveis de aparelho (full, lite, static); sem WebGL fica o pôster
- título novo: "Sites e sistemas sob medida para o jeito que a sua empresa trabalha."
- faixa de clientes com o ramo, linha do primeiro passo, hero alinhado às seções
- rótulos digitados, entrada dos blocos, cortina de blocos entre páginas e capa
  compartilhada entre a lista de cases e o case

Ofertas
- atendimento no WhatsApp com IA e nota fiscal para a reforma tributária
  (páginas de serviço, cartões da home, formulário e aviso com data de validade)
- página /ia atualizada, com fontes
- peças 3D em loop nos cartões e topos de página (3d/pecas.py)

Design
- hover por papel (bloco nos botões, barra nos links), rótulos sem caixa alta
- um destino por rótulo: "Falar sobre meu projeto" leva ao formulário,
  "Chamar no WhatsApp" abre o WhatsApp
- logo montado em blocos, 404 redesenhado, grades sem célula vazia
- ícones do PWA e manifesto novos

Specs em specs/, contexto de design em DESIGN.md e PRODUCT.md.
2026-11-10 03:48:25 -03:00

172 lines
6.4 KiB
TypeScript

"use client";
import {
openCookiePreferences,
trackEmailClick,
trackSocialClick,
} from "@/lib/analytics";
import {
CONTACT_EMAIL,
IA_PAGE_LABEL,
INSTAGRAM_URL,
LINKEDIN_URL,
type ServiceLink,
} from "@/lib/site-navigation";
import "./conversion.css";
import HoverPrefetchLink from "./HoverPrefetchLink";
import { Logo } from "./Logo";
import WhatsAppLink from "./WhatsAppLink";
const headingClassName =
"font-mono text-[13px] font-medium tracking-[0.02em] text-[var(--meta)]";
// min-h-11 no toque; no desktop os links ficam mais juntos para o rodapé não crescer à toa
const linkClassName =
"inline-flex min-h-11 items-center text-left font-display text-[15px] leading-6 text-[var(--ink-80)] md:min-h-8 underline-offset-4 hover:text-[var(--ink)] hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--ink)]";
export default function Footer({
serviceLinks = [],
}: {
/** Os serviços do hub; app/page.tsx os lê de lib/site-content.ts. */
serviceLinks?: ServiceLink[];
}) {
const currentYear = new Date().getFullYear();
return (
// no celular o botão flutuante do WhatsApp (56 px + 16 px de margem) cobriria a última linha: o rodapé sobe o espaço dele.
// A barra de cookies (fixa no pé da tela) cobriria o logo e o © no fim da página: o rodapé também sobe a altura dela
// (--cookie-bar-height, publicada por GoogleAnalytics enquanto a barra está aberta; sem barra, 0).
<footer className="border-t border-[var(--border)] bg-[var(--paper)] px-[clamp(20px,6vw,64px)] pt-sp-10 pb-[calc(var(--sp-10)+var(--cookie-bar-height,0px))] text-[var(--ink)] max-md:pb-[calc(var(--sp-10)+72px+var(--cookie-bar-height,0px))]">
<div className="ds-section-shell">
<div className="grid gap-sp-8 md:grid-cols-3 md:gap-sp-10">
<section aria-labelledby="footer-contact-title">
<p id="footer-contact-title" className={headingClassName}>
Contato
</p>
<ul className="mt-sp-2">
<li>
<WhatsAppLink
placement="footer"
className={`${linkClassName} font-semibold !text-[var(--ink)] focus-visible:!ring-[var(--ink)] focus-visible:!ring-offset-[var(--paper)]`}
>
Chamar no WhatsApp
</WhatsAppLink>
</li>
<li>
<a
href={`mailto:${CONTACT_EMAIL}`}
onClick={() => trackEmailClick({ placement: "footer" })}
className={`${linkClassName} break-all font-semibold !text-[var(--ink)]`}
>
{CONTACT_EMAIL}
</a>
</li>
<li>
<a
href={LINKEDIN_URL}
target="_blank"
rel="noopener noreferrer"
onClick={() => trackSocialClick({ network: "linkedin" })}
className={linkClassName}
>
LinkedIn
</a>
</li>
<li>
<a
href={INSTAGRAM_URL}
target="_blank"
rel="noopener noreferrer"
onClick={() => trackSocialClick({ network: "instagram" })}
className={linkClassName}
>
Instagram
</a>
</li>
</ul>
<p className="mt-sp-2 font-display text-[15px] leading-6 text-[var(--meta)]">
Garuva, SC · Atendimento remoto em todo o Brasil
</p>
</section>
<nav aria-labelledby="footer-services-title">
<p id="footer-services-title" className={headingClassName}>
Serviços
</p>
<ul className="mt-sp-2">
{serviceLinks.map((service) => (
<li key={service.href}>
<HoverPrefetchLink
href={service.href}
className={linkClassName}
>
{service.label}
</HoverPrefetchLink>
</li>
))}
</ul>
</nav>
<nav aria-labelledby="footer-links-title">
<p id="footer-links-title" className={headingClassName}>
Mais
</p>
<ul className="mt-sp-2">
<li>
<HoverPrefetchLink href="/cases" className={linkClassName}>
Cases
</HoverPrefetchLink>
</li>
<li>
<HoverPrefetchLink href="/ia" className={linkClassName}>
{IA_PAGE_LABEL}
</HoverPrefetchLink>
</li>
<li>
<HoverPrefetchLink
href="/privacidade"
className={linkClassName}
>
Privacidade
</HoverPrefetchLink>
</li>
<li>
<button
type="button"
onClick={openCookiePreferences}
className={`cv-btn-link ${linkClassName}`}
>
Preferências de cookies
</button>
</li>
<li>
<HoverPrefetchLink
href="/curriculo"
className={`${linkClassName} !text-[15px] !text-[var(--meta)]`}
>
Currículo
</HoverPrefetchLink>
</li>
</ul>
</nav>
</div>
<div className="mt-sp-8 flex flex-wrap items-center justify-between gap-x-sp-6 gap-y-sp-3 border-t border-[var(--border)] pt-sp-5">
<HoverPrefetchLink
href="/#home"
aria-label="Evandro.dev.br — início"
className="inline-flex min-h-11 items-center"
>
{/* o ".dev" do logo é limão (#ccff00), quase invisível sobre o papel: o filtro o escurece (de 1,04:1
para 4:1) e o resto do logo, já quase preto, quase não muda */}
<Logo theme="light" className="w-40 [filter:brightness(0.5)]" />
</HoverPrefetchLink>
<p className="font-display text-[15px] leading-6 text-[var(--meta)]">
© {currentYear} Evandro Fonseca Junior. Todos os direitos
reservados.
</p>
</div>
</div>
</footer>
);
}