feat: implement intersection observer for fade-in animations in multiple components

This commit is contained in:
2025-08-05 14:47:13 +05:00
parent 29e7ed77b9
commit 99b2824421
5 changed files with 344 additions and 42 deletions
+78 -10
View File
@@ -1,11 +1,58 @@
/* eslint-disable @next/next/no-img-element */
import { gothampro } from "@/utils/fonts";
import Button from "./Button";
import { useEffect, useRef } from "react";
function Info() {
const containerRef = useRef<HTMLDivElement>(null);
const elementsRef = useRef<(HTMLDivElement | null)[]>([]);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("animate-fade-in-up");
entry.target.classList.remove("opacity-0", "translate-y-8");
}
});
},
{ threshold: 0.1, rootMargin: "0px 0px -50px 0px" }
);
elementsRef.current.forEach((el) => {
if (el) observer.observe(el);
});
return () => observer.disconnect();
}, []);
const addToRefs = (el: HTMLDivElement | null) => {
if (el && !elementsRef.current.includes(el)) {
elementsRef.current.push(el);
}
};
return (
<div id="info" className={gothampro.className}>
<style jsx>{`
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-in-up {
animation: fadeInUp 0.6s ease-out forwards;
}
`}</style>
<div
ref={containerRef}
className="bg-[#161616] relative overflow-hidden px-4"
style={{
backgroundImage: `url('/images/noise.svg')`,
@@ -15,7 +62,10 @@ function Info() {
}}
>
<div className="container mx-auto pt-36">
<div className="flex flex-row">
<div
ref={addToRefs}
className="flex flex-row opacity-0 translate-y-8 transition-all duration-700"
>
<div className="flex-1 basis-1/3">
<p className="text-white opacity-60 text-sm md:text-base uppercase font-medium">
[ о нас ]
@@ -30,7 +80,10 @@ function Info() {
</div>
</div>
<div className="flex flex-row">
<div
ref={addToRefs}
className="flex flex-row opacity-0 translate-y-8 transition-all duration-700 delay-200"
>
<div className="flex-1 basis-2/12"></div>
<div className="flex-col max-w-10/12">
@@ -41,7 +94,10 @@ function Info() {
</div>
</div>
<div className="flex flex-row mt-8">
<div
ref={addToRefs}
className="flex flex-row mt-8 opacity-0 translate-y-8 transition-all duration-700 delay-300"
>
<div className="flex-1 basis-1/3"></div>
<div className="flex-col max-w-2/3">
@@ -60,7 +116,10 @@ function Info() {
</div>
</div>
<div className="flex flex-row mt-8">
<div
ref={addToRefs}
className="flex flex-row mt-8 opacity-0 translate-y-8 transition-all duration-700 delay-500"
>
<div className="flex-1 basis-1/3"></div>
<div className="flex-col md:min-w-2/3 justify-start items-start">
@@ -81,27 +140,36 @@ function Info() {
</div>
<div className="container mx-auto flex flex-col md:flex-row pt-12 md:pt-24 pb-28 md:pb-56 gap-4 md:gap-0">
<div className="w-full md:w-1/3 flex justify-center md:justify-start">
<div
ref={addToRefs}
className="w-full md:w-1/3 flex justify-center md:justify-start opacity-0 translate-y-8 transition-all duration-700 delay-700"
>
<img
src="/images/info/moto.png"
alt="moto"
className="w-3/4 md:w-1/2 h-auto object-cover"
className="w-3/4 md:w-1/2 h-auto object-cover hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="w-full md:w-1/3 flex justify-center">
<div
ref={addToRefs}
className="w-full md:w-1/3 flex justify-center opacity-0 translate-y-8 transition-all duration-700 delay-900"
>
<img
src="/images/info/podium.jpg"
alt="car"
className="w-3/4 md:w-full h-auto object-cover"
className="w-3/4 md:w-full h-auto object-cover hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="flex w-full md:w-1/3 justify-center md:justify-start">
<div
ref={addToRefs}
className="flex w-full md:w-1/3 justify-center md:justify-start opacity-0 translate-y-8 transition-all duration-700 delay-1000"
>
<div className="w-0 md:w-1/3"></div>
<div className="w-3/4 md:w-2/3">
<img
src="/images/info/jump.png"
alt="jump"
className="w-full h-auto object-cover"
className="w-full h-auto object-cover hover:scale-105 transition-transform duration-300"
/>
</div>
</div>