- Replace Vite + React Router with Next.js 15 App Router - Implement i18n with next-intl (URL-based: /de, /en, /sr) - Add SSR/SSG for all pages (48 static pages generated) - Setup Supabase SSR client for auth - Migrate all pages: Home, About, Portfolio, Blog, Contact, Login, Dashboard, Imprint, Privacy, Terms - Add Docker support with standalone output - Replace i18next with next-intl JSON translations - Use next/image for optimized images Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { motion, useAnimation } from "framer-motion"
|
|
import { useEffect, useRef } from "react"
|
|
|
|
interface ScrollAnimationProps {
|
|
children: React.ReactNode
|
|
delay?: number
|
|
}
|
|
|
|
const ScrollAnimation: React.FC<ScrollAnimationProps> = ({ children, delay = 0 }) => {
|
|
const controls = useAnimation()
|
|
const ref = useRef<HTMLDivElement>(null)
|
|
|
|
useEffect(() => {
|
|
const observer = new IntersectionObserver(
|
|
([entry]) => {
|
|
if (entry.isIntersecting) {
|
|
controls.start({ opacity: 1, y: 0, transition: { duration: 0.5, delay: delay } })
|
|
}
|
|
},
|
|
{
|
|
threshold: 0.5,
|
|
},
|
|
)
|
|
|
|
if (ref.current) {
|
|
observer.observe(ref.current)
|
|
}
|
|
|
|
return () => {
|
|
if (ref.current) {
|
|
observer.unobserve(ref.current)
|
|
}
|
|
}
|
|
}, [controls, delay])
|
|
|
|
return (
|
|
<motion.div ref={ref} initial={{ opacity: 0, y: 20 }} animate={controls}>
|
|
{children}
|
|
</motion.div>
|
|
)
|
|
}
|
|
|
|
export default ScrollAnimation
|
|
|