feat: add animated components for enhanced UI/UX

- Introduced DrawLine component for drawing animations.
- Added LazyRevealImage component for lazy loading images with reveal animations.
- Implemented TextDiffuseReveal for animated text reveals with staggered effects.
- Created TopProgressBar for a dynamic loading indicator.
- Added PointCloud mock for testing animations.
- Developed useReducedMotion hook to handle user preferences for reduced motion.
- Centralized animation configurations in config.ts for easier management.
- Defined animation variants in variants.ts for consistent animation effects.
- Established AnimationProvider to supply global animation settings.
- Created tests for AnimationProvider and useReducedMotion hook.
- Added SVG assets for branding and UI elements.
- Documented frontend review plan and hero circuit board animation plan.
This commit is contained in:
Evandro Fonseca Junior committed 2026-03-15 21:06:43 -03:00
1 parent 0ab6930f92
commit 08dd046887
76 files changed
+21682 -1197

No files matched your search

+102 -180
View File
@@ -1,8 +1,8 @@
"use client";
import { useState } from "react";
import { motion, type Variants, useReducedMotion } from "framer-motion";
import { Section } from "./Section";
import { Reveal } from "./Reveal";
import { DrawLine } from "./animations/DrawLine";
interface Tier {
id: string;
@@ -24,20 +24,20 @@ const TIERS: Tier[] = [
id: "discovery",
badge: "Entrada / Baixo Risco",
level: "01",
title: "Auditoria & Diagnóstico Técnico",
title: "Auditoria & Diagnostico Tecnico",
tagline: "Fotografia clara do problema antes de qualquer comprometimento.",
description:
"Análise profunda de arquitetura, performance ou segurança com entrega de um plano de ação executável. Ideal para quem precisa de direção antes de contratar execução.",
"Analise profunda de arquitetura, performance ou seguranca com entrega de um plano de acao executavel. Ideal para quem precisa de direcao antes de contratar execucao.",
deliverables: [
"Relatório de gargalos e dívida técnica",
"Mapeamento de riscos e dependências",
"Sugestão de stack e cronograma de mitigação",
"Plano de ação priorizado",
"Relatorio de gargalos e divida tecnica",
"Mapeamento de riscos e dependencias",
"Sugestao de stack e cronograma de mitigacao",
"Plano de acao priorizado",
],
pricing: "Valor Fixo",
pricingNote: "Contrato único. Entrega em até 5 dias úteis.",
pricingNote: "Contrato unico. Entrega em ate 5 dias uteis.",
featured: false,
ctaLabel: "Solicitar diagnóstico",
ctaLabel: "Solicitar diagnostico",
ctaHref: "#contact",
},
{
@@ -47,12 +47,12 @@ const TIERS: Tier[] = [
title: "Ciclos de Engenharia",
tagline: "Capacidade produtiva garantida. Entrega a cada 2 semanas.",
description:
"Desenvolvimento contínuo com a previsibilidade de orçamento do escopo fechado e a agilidade de sprints. Milestones claros, sem amarras de contrato longo.",
"Desenvolvimento continuo com a previsibilidade de orcamento do escopo fechado e a agilidade de sprints. Milestones claros, sem amarras de contrato longo.",
deliverables: [
"Features em produção a cada ciclo",
"Refatoração iterativa com rastreabilidade",
"Documentação técnica atualizada",
"Capacidade de pivotar prioridades no início de cada sprint",
"Features em producao a cada ciclo",
"Refatoracao iterativa com rastreabilidade",
"Documentacao tecnica atualizada",
"Capacidade de pivotar prioridades no inicio de cada sprint",
],
pricing: "Fixo por Ciclo",
pricingNote: "Assinatura quinzenal ou mensal. Cancele a qualquer ciclo.",
@@ -65,226 +65,148 @@ const TIERS: Tier[] = [
badge: "Premium / High-Ticket",
level: "03",
title: "Fractional Tech Lead",
tagline: "Liderança técnica senior. Sem o custo de um CTO full-time.",
tagline: "Lideranca tecnica senior. Sem o custo de um CTO full-time.",
description:
"Direção arquitetural, gestão de risco e sustentação de operações críticas. Para empresas que precisam de decisões de alto impacto com responsabilidade contínua.",
"Direcao arquitetural, gestao de risco e sustentacao de operacoes criticas. Para empresas que precisam de decisoes de alto impacto com responsabilidade continua.",
deliverables: [
"SLA prioritário Zero-Risk",
"Code review e liderança do time interno",
"Decisões de infra: Cloud, VPS, CI/CD",
"Consultoria estratégica recorrente",
"SLA prioritario Zero-Risk",
"Code review e lideranca do time interno",
"Decisoes de infra: Cloud, VPS, CI/CD",
"Consultoria estrategica recorrente",
],
pricing: "Retainer Mensal",
pricingNote: "Renovação mensal. Vagas limitadas.",
pricingNote: "Renovacao mensal. Vagas limitadas.",
featured: false,
ctaLabel: "Agendar conversa estratégica",
ctaLabel: "Agendar conversa estrategica",
ctaHref: "#contact",
},
];
function TierCard({ tier }: { tier: Tier }) {
const [hovered, setHovered] = useState(false);
function TierCard({ tier }: Readonly<{ tier: Tier }>) {
const shouldReduceMotion = useReducedMotion();
return (
<article
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
onFocus={() => setHovered(true)}
onBlur={() => setHovered(false)}
<motion.article
tabIndex={0}
className={`ds-card h-full relative outline-none ${
tier.featured ? "border-[var(--slash)] shadow-sm" : ""
}`}
style={{
border: tier.featured
? "2px solid #0A0A0A"
: "1px solid rgba(10,10,10,0.1)",
background: tier.featured ? "#0A0A0A" : "#fff",
padding: "var(--sp-6)",
display: "flex",
flexDirection: "column",
gap: "var(--sp-4)",
position: "relative",
transition: "border-color 0.3s ease, box-shadow 0.3s ease",
outline: "none",
cursor: "default",
boxShadow: hovered
? "0 8px 32px rgba(10,10,10,0.1)"
: "0 1px 4px rgba(10,10,10,0.04)",
borderWidth: tier.featured ? "2px" : "1px",
}}
whileHover={
shouldReduceMotion
? undefined
: {
y: -4,
boxShadow: "0 24px 50px rgba(0, 0, 0, 0.08)",
}
}
whileTap={shouldReduceMotion ? undefined : { scale: 0.99 }}
transition={{ type: "spring", stiffness: 180, damping: 18 }}
>
{/* Top row */}
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "flex-start",
}}
>
<span
style={{
fontSize: "9px",
letterSpacing: "0.16em",
textTransform: "uppercase",
color: tier.featured ? "#E8FF00" : "rgba(10,10,10,0.4)",
}}
>
{tier.badge}
</span>
<span
style={{
fontFamily: "var(--font-display)",
fontSize: "11px",
color: tier.featured
? "rgba(255,255,255,0.15)"
: "rgba(10,10,10,0.12)",
fontWeight: 800,
letterSpacing: "0.04em",
}}
>
<div className="flex justify-between items-start">
<span className="ds-kicker">{tier.badge}</span>
<span className="font-display text-[11px] font-extrabold tracking-widest text-[var(--meta)]">
{tier.level}
</span>
</div>
{/* Title */}
<div>
<h3
style={{
fontFamily: "var(--font-display)",
fontSize: "clamp(18px, 2.2vw, 26px)",
lineHeight: 1.1,
letterSpacing: "-0.02em",
fontWeight: 800,
color: tier.featured ? "#fff" : "#0A0A0A",
}}
>
{tier.title}
</h3>
<p
style={{
marginTop: "var(--sp-2)",
fontSize: "11px",
color: tier.featured
? "rgba(232,255,0,0.85)"
: "rgba(10,10,10,0.5)",
lineHeight: 1.6,
}}
>
<DrawLine delay={0.04} />
<div className="mt-sp-4">
<h3 className="ds-card-title">{tier.title}</h3>
<p className="mt-sp-2 text-[11px] font-medium leading-relaxed text-[var(--meta)]">
{tier.tagline}
</p>
</div>
{/* Description */}
<p
style={{
fontSize: "12px",
color: tier.featured
? "rgba(255,255,255,0.7)"
: "rgba(10,10,10,0.65)",
lineHeight: 1.8,
}}
>
{tier.description}
</p>
<p className="ds-copy">{tier.description}</p>
{/* Deliverables */}
<ul
style={{
paddingLeft: "var(--sp-5)",
fontSize: "12px",
color: tier.featured ? "rgba(255,255,255,0.6)" : "rgba(10,10,10,0.6)",
lineHeight: 1.9,
flexGrow: 1,
}}
>
{tier.deliverables.map((d) => (
<li key={d} style={{ listStyleType: "disc" }}>
{d}
</li>
<ul className="ds-list">
{tier.deliverables.map((deliverable) => (
<li key={deliverable}>{deliverable}</li>
))}
</ul>
{/* Pricing */}
<div
style={{
borderTop: tier.featured
? "1px solid rgba(255,255,255,0.1)"
: "1px solid rgba(10,10,10,0.08)",
paddingTop: "var(--sp-4)",
}}
>
<div
style={{
fontFamily: "var(--font-display)",
fontSize: "clamp(14px, 1.5vw, 18px)",
fontWeight: 800,
color: tier.featured ? "#E8FF00" : "#0A0A0A",
letterSpacing: "-0.01em",
}}
>
<div className="mt-sp-6 border-t border-[var(--border)] pt-sp-4">
<div className="font-display text-[clamp(14px,1.5vw,18px)] font-extrabold tracking-tight">
{tier.pricing}
</div>
<div
style={{
fontSize: "10px",
color: tier.featured
? "rgba(255,255,255,0.3)"
: "rgba(10,10,10,0.35)",
marginTop: "4px",
letterSpacing: "0.06em",
}}
>
<div className="mt-1 text-[10px] tracking-widest text-[var(--meta)] uppercase">
{tier.pricingNote}
</div>
</div>
{/* CTA — reveals on hover/focus */}
<a
<motion.a
href={tier.ctaHref}
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
padding: "12px 18px",
fontSize: "10px",
letterSpacing: "0.12em",
textTransform: "uppercase",
textDecoration: "none",
fontWeight: 700,
background: tier.featured ? "#E8FF00" : "#0A0A0A",
color: tier.featured ? "#0A0A0A" : "#fff",
transition: "opacity 0.25s ease, transform 0.25s ease",
opacity: hovered ? 1 : 0,
transform: hovered ? "translateY(0)" : "translateY(6px)",
pointerEvents: hovered ? "auto" : "none",
}}
className={`ds-link mt-sp-6 justify-center w-full ${
tier.featured ? "ds-link-accent" : "ds-link-muted"
}`}
whileHover={shouldReduceMotion ? undefined : { scale: 1.02 }}
whileTap={shouldReduceMotion ? undefined : { scale: 0.98 }}
transition={{ type: "spring", stiffness: 260, damping: 20 }}
>
{tier.ctaLabel} →
</a>
</article>
{tier.ctaLabel}
{" ->"}
</motion.a>
</motion.article>
);
}
export function WorkModalities() {
const shouldReduceMotion = useReducedMotion();
const containerVariants: Variants = {
hidden: {},
visible: {
transition: {
delayChildren: 0.08,
staggerChildren: 0.08,
},
},
};
const itemVariants: Variants = {
hidden: shouldReduceMotion
? { opacity: 0 }
: { opacity: 0, y: 20, clipPath: "inset(100% 0 0 0)" },
visible: {
opacity: 1,
y: 0,
clipPath: "inset(0% 0 0 0)",
transition: shouldReduceMotion
? { duration: 0.25 }
: { duration: 0.75, ease: [0.16, 1, 0.3, 1] },
},
};
return (
<Section
id="modalities"
eyebrow="CONTRACT_PROTOCOLS.sys"
title="Engenharia sob demanda. Previsibilidade de entrega sem overhead."
description="Três níveis de contratação desenhados como uma esteira de valor — do diagnóstico rápido à parceria estratégica de longo prazo."
description="Tres niveis de contratacao desenhados como uma esteira de valor, do diagnostico rapido a parceria estrategica de longo prazo."
disableChildrenAnimation
>
<div
<motion.div
style={{
display: "grid",
gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
gap: "var(--sp-6)",
}}
className="max-md:grid-cols-1 max-md:!flex max-md:!flex-col"
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={containerVariants}
>
{TIERS.map((tier, index) => (
<Reveal key={tier.id} y={40} duration={0.8} delay={0.1 * index}>
{TIERS.map((tier) => (
<motion.div key={tier.id} variants={itemVariants}>
<TierCard tier={tier} />
</Reveal>
</motion.div>
))}
</div>
</motion.div>
</Section>
);
}