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

+118 -48
View File
@@ -1,17 +1,23 @@
"use client";
import { motion, type Variants, useReducedMotion } from "framer-motion";
import profilePhoto from "@/public/edev.jpeg";
import { Section } from "./Section";
import { Reveal } from "./Reveal";
import { DrawLine } from "./animations/DrawLine";
import { LazyRevealImage } from "./animations/LazyRevealImage";
const STORY_DATA = [
{
id: "KERNEL_INIT",
title: "Engenharia de fundamentos",
id: "HARDWARE_BRIDGE",
title: "Do físico ao digital",
content:
"Projeto sistemas com foco em previsibilidade, manutenção e crescimento real. Escala entra na arquitetura desde o início.",
"Construo a ponte entre hardware e software. Projeto sistemas capazes de orquestrar dispositivos físicos, protocolos de baixo nível e interfaces web modernas com baixa latência e alta resiliência.",
},
{
id: "RUNTIME_EXEC",
title: "Entrega sob restrições",
content:
"Atuo bem em cenários com legado, prazos apertados e decisões de produto em movimento, sem sacrificar legibilidade técnica.",
"Atuo com naturalidade em cenários críticos envolvendo integrações de hardware, APIs complexas e infraestrutura legada, sempre priorizando a estabilidade e a legibilidade técnica.",
},
];
@@ -19,77 +25,141 @@ const VALUES_DATA = [
{
title: "Pragmatismo arquitetural",
description:
"Decisões guiadas por ROI, operabilidade e clareza para o time que mantém o sistema depois.",
"Decisões guiadas por contexto real e operabilidade. A melhor tecnologia é aquela que resolve o problema sem adicionar complexidade inútil ao sistema.",
},
{
title: "Fundação técnica",
title: "Fundação & Integração",
description:
"Fundamentos fortes em dados, protocolos e modelagem para evitar soluções frágeis e modismos vazios.",
"Domínio de protocolos de rede e arquiteturas distribuídas para conectar desde microcontroladores até sistemas robustos na nuvem.",
},
{
title: "Ownership real",
title: "Ownership ponta a ponta",
description:
"Responsabilidade sobre entrega, comunicação e qualidade final, não só sobre o trecho de código escrito.",
"Responsabilidade que atravessa camadas: do pulso elétrico no hardware até a renderização do último componente na tela do usuário.",
},
{
title: "Security by design",
title: "Security & Safety",
description:
"Integridade, proteção de dados e conformidade tratadas como parte do produto, não como remendo.",
"Segurança e resiliência tratadas como base. Sistemas desenhados para falhar graciosamente e proteger dados do dispositivo à nuvem.",
},
];
export default function About() {
const shouldReduceMotion = useReducedMotion();
const staggerContainer: Variants = {
hidden: {},
visible: {
transition: {
delayChildren: 0.08,
staggerChildren: 0.08,
},
},
};
const cardVariants: 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.8,
ease: [0.16, 1, 0.3, 1],
},
},
};
const cardHover = shouldReduceMotion
? undefined
: {
y: -4,
boxShadow: "0 18px 40px rgba(10,10,10,0.16)",
};
return (
<Section
id="about"
eyebrow="WHOAMI.sys"
title="Engenharia orientada por clareza, não por ruído"
description="Transformo complexidade técnica em sistemas estáveis, operáveis e alinhados ao negócio."
title="Engenharia orientada por clareza, nao por ruido"
description="Transformo complexidade tecnica em sistemas estaveis, operaveis e alinhados ao negocio."
disableChildrenAnimation
aside={
<div className="mt-sp-4 ds-metric">
<span className="inline-block h-1.5 w-1.5 rounded-full bg-slash" />
Garuva, SC · Remote worldwide
Garuva, SC | Remote worldwide
</div>
}
>
<div className="ds-grid-2">
<div className="ds-grid-2">
{STORY_DATA.map((step, index) => (
<Reveal key={step.id} y={30} duration={0.8} delay={0.1 * index}>
<article className="ds-card h-full">
<div className="ds-kicker">{step.id}</div>
<h3 className="ds-card-title">{step.title}</h3>
<p className="ds-copy">{step.content}</p>
</article>
</Reveal>
<motion.div
className="ds-grid-2"
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
variants={staggerContainer}
>
<motion.div
className="flex flex-col gap-sp-6"
variants={staggerContainer}
>
{STORY_DATA.map((step) => (
<motion.article
key={step.id}
className="ds-card"
variants={cardVariants}
whileHover={cardHover}
whileTap={shouldReduceMotion ? undefined : { scale: 0.99 }}
transition={{ type: "spring", stiffness: 180, damping: 18 }}
>
<div className="ds-kicker">{step.id}</div>
<DrawLine delay={0.03} />
<h3 className="ds-card-title">{step.title}</h3>
<p className="ds-copy">{step.content}</p>
</motion.article>
))}
</div>
</motion.div>
<Reveal y={30} duration={0.8} delay={0.2}>
<div className="ds-card h-full">
<div className="ds-kicker">System Signature</div>
<h3 className="ds-card-title">Base técnica e postura de entrega</h3>
<p className="ds-copy">
Evandro Fonseca Junior. Engenheiro Full-Stack com foco em Next.js,
React, Node.js, Tauri, integrações e arquitetura pragmática.
</p>
<div className="ds-grid-2 mt-sp-6">
{VALUES_DATA.map((value) => (
<div
key={value.title}
className="border-t border-[var(--border)] pt-sp-4"
>
<div className="text-[11px] font-medium uppercase tracking-[0.08em]">
{value.title}
</div>
<p className="ds-copy !mt-sp-2">{value.description}</p>
<motion.article
className="ds-card h-full"
variants={cardVariants}
whileHover={cardHover}
whileTap={shouldReduceMotion ? undefined : { scale: 0.99 }}
transition={{ type: "spring", stiffness: 180, damping: 18 }}
>
<LazyRevealImage
src={profilePhoto}
alt="Retrato de Evandro"
className="mb-sp-6 h-[220px] w-full overflow-hidden rounded-[6px] border border-[var(--border)]"
imageClassName="object-cover"
/>
<div className="ds-kicker">System Signature</div>
<DrawLine delay={0.05} />
<h3 className="ds-card-title">Base tecnica e postura de entrega</h3>
<p className="ds-copy">
Evandro Fonseca Junior. Engenheiro de Software Full-Stack com foco
na convergência entre hardware e aplicações web modernas.
Especialista em TypeScript, Node.js, ecossistema React e automação
de dispositivos físicos.
</p>
<div className="ds-grid-2 mt-sp-6">
{VALUES_DATA.map((value) => (
<div
key={value.title}
className="border-t border-[var(--border)] pt-sp-4"
>
<div className="text-[11px] font-medium uppercase tracking-[0.08em]">
{value.title}
</div>
))}
</div>
<p className="ds-copy !mt-sp-2">{value.description}</p>
</div>
))}
</div>
</Reveal>
</div>
</motion.article>
</motion.div>
</Section>
);
}