Files
portifolio-evandrodevbr/app/components/animations/TextDiffuseReveal.tsx
T
Evandro Fonseca JuniorandClaude Opus 5.5 def1e22302 perf(home): transicoes de Qualidade so com translate/opacity e titulos por palavra em CSS
Medido com trace do Chromium (rasterizacao no mesmo trecho de rolagem):
IA->Qualidade 840->558 ms, dentro de Qualidade 34->18 ms, Qualidade->Sobre
819->643 ms. Recorte animado, escala de camadas grandes e o desenho do diagrama
a cada quadro saem; o diagrama se desenha uma vez em CSS. TextDiffuseReveal
deixa de animar cada letra com desfoque.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 01:19:48 -03:00

57 lines
1.6 KiB
TypeScript

"use client";
import { useInView } from "motion/react";
import { type CSSProperties, useRef } from "react";
interface TextDiffuseRevealProps {
text: string;
className?: string;
startDelay?: number;
once?: boolean;
amount?: number;
}
/**
* Título que entra palavra por palavra. A animação é CSS (.text-reveal em globals.css) com transparência
* e deslocamento: a placa de vídeo compõe sem redesenhar. A versão anterior animava cada letra com
* desfoque e renderizava o React de novo a cada letra, o que pesava justamente durante as transições.
* Movimento reduzido: o CSS mostra o texto direto, sem animação.
*/
export function TextDiffuseReveal({
text,
className = "",
startDelay = 0,
once = true,
amount = 0.3,
}: Readonly<TextDiffuseRevealProps>) {
const ref = useRef<HTMLSpanElement | null>(null);
const isInView = useInView(ref, { once, amount });
let word = 0;
return (
<span
ref={ref}
className={`text-reveal ${className}`.trim()}
data-shown={isInView ? "" : undefined}
style={{ "--d": `${startDelay}s` } as CSSProperties}
>
<span className="sr-only">{text}</span>
<span aria-hidden="true">
{text
.split(/(\n|\s+)/)
.filter(Boolean)
.map((token, index) => {
const key = `${index}:${token}`;
if (token === "\n") return <br key={key} />;
if (/^\s+$/.test(token)) return " ";
return (
<span key={key} className="text-reveal-word" style={{ "--i": word++ } as CSSProperties}>
{token}
</span>
);
})}
</span>
</span>
);
}