Files
homaroma/apps/spa/src/components/ScrollReveal.tsx
T
2026-06-29 19:24:57 -04:00

53 lines
1.8 KiB
TypeScript

import { useScrollReveal } from '../hooks/useScrollReveal';
// Animation style -> initial transform mapping
const STYLE_TRANSFORMS: Record<string, string> = {
'fade-up': 'translateY(28px)',
'fade-in': 'translateY(0)',
'slide-left': 'translateX(28px)',
'zoom-in': 'scale(0.95)',
'none': 'translateY(0)',
}
interface ScrollRevealProps {
children: React.ReactNode;
delay?: number; // ms
className?: string;
}
export default function ScrollReveal({ children, delay = 0, className = '' }: ScrollRevealProps) {
const { ref, isVisible } = useScrollReveal<HTMLDivElement>({
threshold: 0.08,
rootMargin: '0px 0px -40px 0px',
});
// อ่านค่าจาก CSS variables ที่ ThemeInjector inject ไว้
const root = typeof window !== 'undefined' ? document.documentElement : null
const enabled = root?.style.getPropertyValue('--scroll-reveal-enabled').trim() !== '0'
const style = root?.style.getPropertyValue('--scroll-reveal-style').trim() || 'fade-up'
const durationVar = root?.style.getPropertyValue('--scroll-reveal-duration').trim() || '700ms'
const durationMs = parseInt(durationVar) || 700
// ถ้าปิด animation ให้แสดงปกติเลย
if (!enabled || style === 'none') {
return <div className={className}>{children}</div>
}
const initialTransform = STYLE_TRANSFORMS[style] ?? STYLE_TRANSFORMS['fade-up']
return (
<div
ref={ref}
className={className}
style={{
opacity: isVisible ? 1 : 0,
transform: isVisible ? 'translateY(0) translateX(0) scale(1)' : initialTransform,
transition: `opacity ${durationMs}ms ease-out ${delay}ms, transform ${durationMs}ms ease-out ${delay}ms`,
willChange: 'opacity, transform',
}}
>
{children}
</div>
);
}