101 lines
3.2 KiB
TypeScript
101 lines
3.2 KiB
TypeScript
import { motion, AnimatePresence } from "framer-motion";
|
|
import { useState, useEffect } from "react";
|
|
|
|
interface BioSectionProps {
|
|
imageSrc: string;
|
|
imageAlt: string;
|
|
text: string;
|
|
reversed?: boolean;
|
|
}
|
|
|
|
export default function BioSection({ imageSrc, imageAlt, text, reversed = false }: BioSectionProps) {
|
|
const images = imageSrc.split(',').map(src => src.trim()).filter(src => src.length > 0);
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
const [prevIndex, setPrevIndex] = useState(0);
|
|
const [direction, setDirection] = useState(1); // 1 for right, -1 for left (though we always slide right here)
|
|
|
|
useEffect(() => {
|
|
if (images.length <= 1) return;
|
|
|
|
const interval = setInterval(() => {
|
|
setPrevIndex(currentIndex);
|
|
setCurrentIndex((prev) => (prev + 1) % images.length);
|
|
}, 6000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [images.length, currentIndex]);
|
|
|
|
const slideVariants = {
|
|
enter: {
|
|
x: "-100%",
|
|
opacity: 1
|
|
},
|
|
center: {
|
|
x: 0,
|
|
opacity: 1
|
|
},
|
|
exit: {
|
|
x: "100%",
|
|
opacity: 1
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className="about-content"
|
|
style={{
|
|
flexDirection: reversed ? "row-reverse" : "row",
|
|
}}
|
|
>
|
|
<motion.div
|
|
className="about-image-container"
|
|
initial={{ x: reversed ? 30 : -30, opacity: 0 }}
|
|
animate={{ x: 0, opacity: 1 }}
|
|
transition={{ delay: 0.4, duration: 0.6 }}
|
|
style={{
|
|
position: "relative",
|
|
width: "250px",
|
|
height: "250px",
|
|
overflow: "hidden",
|
|
borderRadius: "20px",
|
|
border: "3px solid rgba(255, 255, 255, 0.8)",
|
|
boxShadow: "0 8px 32px rgba(0, 0, 0, 0.2)",
|
|
}}
|
|
>
|
|
<AnimatePresence initial={false}>
|
|
<motion.img
|
|
key={currentIndex}
|
|
src={images[currentIndex]}
|
|
alt={imageAlt}
|
|
variants={slideVariants}
|
|
initial="enter"
|
|
animate="center"
|
|
exit="exit"
|
|
transition={{ duration: 0.8, ease: "easeInOut" }}
|
|
style={{
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
width: "100%",
|
|
height: "100%",
|
|
objectFit: "cover",
|
|
}}
|
|
whileHover={{ scale: 1.05 }}
|
|
/>
|
|
</AnimatePresence>
|
|
</motion.div>
|
|
|
|
<motion.div
|
|
className="about-text-container"
|
|
initial={{ x: reversed ? -30 : 30, opacity: 0 }}
|
|
animate={{ x: 0, opacity: 1 }}
|
|
transition={{ delay: 0.6, duration: 0.6 }}
|
|
>
|
|
<p className="about-text">
|
|
{text}
|
|
</p>
|
|
</motion.div>
|
|
</div>
|
|
);
|
|
}
|