diff --git a/src/components/about-page.tsx b/src/components/about-page.tsx index 6cc2224..b62692c 100644 --- a/src/components/about-page.tsx +++ b/src/components/about-page.tsx @@ -260,8 +260,12 @@ function About() { role="list" className="grid gap-x-8 gap-y-12 sm:grid-cols-2 sm:gap-y-16 xl:col-span-2" > - {people.map((person) => ( - + {people.map((person, index) => ( + ))} @@ -270,10 +274,11 @@ function About() {
- {testimonials.map((testimonial) => ( + {testimonials.map((testimonial, index) => ( ))}
@@ -311,10 +316,11 @@ function About() {
- {testimonials.map((testimonial) => ( + {testimonials.map((testimonial, index) => ( ))}
diff --git a/src/components/about/animated-image-gallery.tsx b/src/components/about/animated-image-gallery.tsx index e604aa0..31317e0 100644 --- a/src/components/about/animated-image-gallery.tsx +++ b/src/components/about/animated-image-gallery.tsx @@ -1,24 +1,49 @@ -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' const AnimatedImageGallery = () => { - const imageRefs = [useRef(null), useRef(null)] + const [isDesktop, setIsDesktop] = useState(false) + const [isLoaded, setIsLoaded] = useState(false) + const imageRefs = [ + useRef(null), + useRef(null), + useRef(null), + useRef(null), + useRef(null), + ] useEffect(() => { - if (window.innerWidth >= 640) return + setIsDesktop(window.innerWidth >= 640) + setIsLoaded(true) + }, []) + + useEffect(() => { + if (!isDesktop || !isLoaded) return + + imageRefs.forEach((ref, index) => { + setTimeout(() => { + if (ref.current) { + ref.current.classList.remove('opacity-0', 'translate-y-8') + ref.current.classList.add('opacity-100', 'translate-y-0') + } + }, index * 150) + }) + }, [isDesktop, isLoaded]) - const observers = imageRefs.map((ref, index) => { - const threshold = 0.5 - index * 0.1 + useEffect(() => { + if (isDesktop) return + + const mobileAnimatedRefs = [imageRefs[2], imageRefs[4]] + const observers = mobileAnimatedRefs.map((ref, index) => { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { - if (entry.isIntersecting) { + if (entry.isIntersecting && ref.current) { setTimeout(() => { if (ref.current) { ref.current.classList.remove( 'opacity-0', - 'translate-x-8', - '-translate-x-8', + index === 0 ? '-translate-x-8' : 'translate-x-8', ) ref.current.classList.add('opacity-100', 'translate-x-0') } @@ -28,7 +53,7 @@ const AnimatedImageGallery = () => { }) }, { - threshold, + threshold: 0.2, rootMargin: '0px 0px -10% 0px', }, ) @@ -43,23 +68,41 @@ const AnimatedImageGallery = () => { return () => { observers.forEach((observer) => observer.disconnect()) } - }, []) + }, [isDesktop]) + + const getInitialClasses = (index: number) => { + if (!isLoaded) return 'opacity-0' + + if (isDesktop) { + return 'translate-y-8 transform opacity-0 transition-all duration-700 ease-out' + } + + if (index === 2) { + return '-translate-x-8 transform opacity-0 transition-all duration-700 ease-out' + } + if (index === 4) { + return 'translate-x-8 transform opacity-0 transition-all duration-700 ease-out' + } + return 'transform-none opacity-100' + } return ( <>
- -
+
+ +
+
-
+
{
-
+
{
-
+
{
-
+
{ +const AnimatedTeamMembers = ({ person, index }: AnimatedTeamMemberProps) => { const memberRef = useRef(null) + const [isDesktop, setIsDesktop] = useState(false) useEffect(() => { - if (window.innerWidth >= 640) return + setIsDesktop(window.innerWidth >= 640) + }, []) + useEffect(() => { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { - if (entry.isIntersecting) { - if (memberRef.current) { + if (entry.isIntersecting && memberRef.current) { + if (isDesktop) { + setTimeout(() => { + if (memberRef.current) { + const isLeftColumn = index % 2 === 0 + memberRef.current.classList.remove( + 'opacity-0', + isLeftColumn ? '-translate-x-8' : 'translate-x-8', + ) + memberRef.current.classList.add( + 'opacity-100', + 'translate-x-0', + ) + } + }, index * 150) + } else { memberRef.current.classList.remove('opacity-0', 'translate-y-8') memberRef.current.classList.add('opacity-100', 'translate-y-0') } @@ -42,12 +60,18 @@ const AnimatedTeamMembers = ({ person }: AnimatedTeamMemberProps) => { return () => { observer.disconnect() } - }, []) + }, [isDesktop, index]) + + const initialTransform = isDesktop + ? index % 2 === 0 + ? '-translate-x-8' + : 'translate-x-8' + : 'translate-y-8' return (
  • diff --git a/src/components/about/animated-testimonials.tsx b/src/components/about/animated-testimonials.tsx index 0c96d34..78ea48f 100644 --- a/src/components/about/animated-testimonials.tsx +++ b/src/components/about/animated-testimonials.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' interface TestimonialAuthor { name: string @@ -14,19 +14,42 @@ interface Testimonial { interface AnimatedTestimonialProps { testimonial: Testimonial + index: number } -const AnimatedTestimonials = ({ testimonial }: AnimatedTestimonialProps) => { +const ITEMS_PER_COLUMN = 3 + +const AnimatedTestimonials = ({ + testimonial, + index, +}: AnimatedTestimonialProps) => { const testimonialRef = useRef(null) + const [isDesktop, setIsDesktop] = useState(false) useEffect(() => { - if (window.innerWidth >= 640) return + setIsDesktop(window.innerWidth >= 640) + }, []) + useEffect(() => { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { - if (entry.isIntersecting) { - if (testimonialRef.current) { + if (entry.isIntersecting && testimonialRef.current) { + if (isDesktop) { + const columnIndex = Math.floor(index / ITEMS_PER_COLUMN) + setTimeout(() => { + if (testimonialRef.current) { + testimonialRef.current.classList.remove( + 'opacity-0', + 'translate-y-4', + ) + testimonialRef.current.classList.add( + 'opacity-100', + 'translate-y-0', + ) + } + }, columnIndex * 200) + } else { testimonialRef.current.classList.remove( 'opacity-0', 'translate-y-8', @@ -53,12 +76,14 @@ const AnimatedTestimonials = ({ testimonial }: AnimatedTestimonialProps) => { return () => { observer.disconnect() } - }, []) + }, [isDesktop, index]) + + const initialTransform = isDesktop ? 'translate-y-4' : 'translate-y-8' return (