Files
portifolio-evandrodevbr/app/components/Reveal.tsx
Evandro Fonseca Junior b791b7de9e feat: control room hero, SEO/AEO optimization and design system fixes
Hero: replace particle field with cobe globe (Capricorn view, multi-axis drag, reduced-motion safe), telemetry HUD with pointer parallax, particle text build effect, Space Grotesk display font. SEO: short titles with template, PT-BR accents, twitter cards on dynamic cases, escaped JSON-LD via lib/jsonld.ts, CSP report-only, 25 service FAQs answer-first. Design: fix TW4 layered reset killing spacing utilities, literal @theme tokens, mobile hero overflow, header overlap, empty case cards. Remove framer-motion (unified on motion/react), header version badge, phone number from hero CTA. Production build verified (24 static pages).
2026-08-27 10:55:21 -03:00

70 lines
1.5 KiB
TypeScript

"use client";
import { motion } from "motion/react";
import type { ReactNode } from "react";
import { useState } from "react";
import { useReducedMotion } from "@/app/hooks/useReducedMotion";
interface RevealProps {
children: ReactNode;
y?: number;
duration?: number;
delay?: number;
ease?: string;
start?: string;
end?: string;
scrub?: boolean | number;
className?: string;
}
export function Reveal({
children,
y = 36,
duration = 0.8,
delay = 0,
className = "",
}: RevealProps) {
const shouldReduceMotion = useReducedMotion();
const [animating, setAnimating] = useState(!shouldReduceMotion);
return (
<motion.div
className={className}
initial={
shouldReduceMotion
? { opacity: 0 }
: { opacity: 0, y, clipPath: "inset(100% 0 0 0)" }
}
whileInView={
shouldReduceMotion
? { opacity: 1 }
: { opacity: 1, y: 0, clipPath: "inset(0% 0 0 0)" }
}
viewport={{ once: true, amount: 0.2 }}
transition={
shouldReduceMotion
? { duration: 0.25 }
: {
duration,
delay,
ease: [0.16, 1, 0.3, 1],
}
}
style={{
willChange:
animating && !shouldReduceMotion
? "transform, opacity, clip-path"
: undefined,
}}
onAnimationStart={() => {
if (!shouldReduceMotion) {
setAnimating(true);
}
}}
onAnimationComplete={() => setAnimating(false)}
>
{children}
</motion.div>
);
}