Files
klz-cables.com/components/blog/AnimatedImage.tsx
Marc Mintel f7aa880d9f
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 1m19s
Build & Deploy / 🧪 QA (push) Failing after 3m32s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🏗️ Build (push) Failing after 7m51s
Build & Deploy / ⚡ Lighthouse (push) Has been skipped
Build & Deploy / 🧪 Smoke Test (push) Has been skipped
Build & Deploy / ♿ WCAG (push) Has been skipped
Build & Deploy / 🛡️ Quality Gates (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 10s
feat: migration von directus zu payloadcms
2026-02-24 19:25:43 +01:00

78 lines
1.9 KiB
TypeScript

'use client';
import React, { useState, useEffect, useRef } from 'react';
import Image from 'next/image';
interface AnimatedImageProps {
src: string;
alt: string;
width?: number;
height?: number;
className?: string;
priority?: boolean;
}
export default function AnimatedImage({
src,
alt,
width = 800,
height = 600,
className = '',
priority = false,
}: AnimatedImageProps) {
const [isLoaded, setIsLoaded] = useState(false);
const [isInView, setIsInView] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsInView(true);
observer.disconnect();
}
});
},
{ threshold: 0.1 },
);
if (containerRef.current) {
observer.observe(containerRef.current);
}
return () => observer.disconnect();
}, []);
return (
<div
ref={containerRef}
className={`relative overflow-hidden rounded-2xl shadow-2xl my-16 group ${className}`}
>
<div
className={`
absolute inset-0 bg-primary/10 z-10 pointer-events-none transition-opacity duration-1000
${isLoaded && isInView ? 'opacity-0' : 'opacity-100'}
`}
/>
<Image
src={src}
alt={alt}
width={width}
height={height}
className={`
duration-[1.5s] ease-out w-full h-auto transition-all
${isLoaded && isInView ? 'scale-100 blur-0 opacity-100' : 'scale-110 blur-2xl opacity-0'}
group-hover:scale-105
`}
onLoad={() => setIsLoaded(true)}
priority={priority}
/>
{/* Subtle reflection overlay */}
<div className="absolute inset-0 bg-gradient-to-tr from-white/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700 pointer-events-none" />
</div>
);
}