Files
reui-blocks/blocks/timeline2.tsx
T

143 lines
5.4 KiB
TypeScript

"use client";
import { useEffect, useRef, useState } from "react";
import { cn } from "@/lib/utils";
const sections = [
{
subTitle: "داشبورد هوشمند",
title: "گردش کار خود را ساده کنید",
description:
"با رابط شهودی ما گردش کار خود را بهینه کنید. به ابزارها و قابلیت‌های قدرتمندی دسترسی داشته باشید که برای افزایش بهره‌وری و کارایی طراحی شده‌اند.",
image:
"/block-media/shadcnblocks/block/placeholder-dark-1.svg",
},
{
subTitle: "مدیریت تیم",
title: "همکاری بی‌نقص با تیم‌ها",
description:
"همکاری روان در سراسر سازمان را ممکن کنید. منابع را با کنترل‌های دسترسی و تنظیمات مجوز قابل سفارشی‌سازی، به‌صورت کارآمد به اشتراک بگذارید.",
image:
"/block-media/shadcnblocks/block/placeholder-dark-2.svg",
},
{
subTitle: "تحلیل پیشرفته",
title: "گزینه‌های پیکربندی انعطاف‌پذیر",
description:
"تجربه خود را با گزینه‌های پیکربندی پیشرفته شخصی‌سازی کنید. پلتفرم را با راهکار چندمنظوره ما مطابق نیازهای خاص خود تطبیق دهید.",
image:
"/block-media/shadcnblocks/block/placeholder-dark-3.svg",
},
{
subTitle: "ابزارهای خودکارسازی",
title: "تجربه کاربری ساده‌شده",
description:
"رابط کاربری دوستانه‌ای را تجربه کنید که برای کارایی طراحی شده است. بلاک‌های شهودی ما کارهای پیچیده را ساده و در دسترس می‌کنند.",
image:
"/block-media/shadcnblocks/block/placeholder-dark-1.svg",
},
];
interface Timeline2Props {
className?: string;
}
const Timeline2 = ({ className }: Timeline2Props) => {
const [activeIndex, setActiveIndex] = useState(0);
const sectionRefs = useRef<(HTMLDivElement | null)[]>([]);
useEffect(() => {
const handleScroll = () => {
const viewportHeight = window.innerHeight;
const viewportCenter = viewportHeight / 2;
let closestSection = 0;
let closestDistance = Infinity;
sectionRefs.current.forEach((section, index) => {
if (section) {
const rect = section.getBoundingClientRect();
const sectionCenter = rect.top + rect.height / 2;
const distance = Math.abs(sectionCenter - viewportCenter);
if (distance < closestDistance) {
closestDistance = distance;
closestSection = index;
}
}
});
setActiveIndex(closestSection);
};
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
<div className="container max-w-7xl">
<h1 className="mb-14 max-w-2xl text-start text-xl font-semibold text-balance md:text-2xll">
گردش کار خود را با راهکار ما متحول کنید
</h1>
<div className="flex justify-between gap-20">
<div className="flex flex-col gap-16 text-start md:w-1/2">
{sections.map((section, index) => (
<div
key={index}
ref={(el) => {
sectionRefs.current[index] = el;
}}
className="flex flex-col gap-4 md:h-[50vh]"
>
<div className="block rounded-2xl border bg-muted p-4 md:hidden">
<img
src={section.image}
alt={section.title}
className="h-full max-h-full w-full max-w-full rounded-2xl object-cover"
/>
</div>
<p className="text-sm font-semibold text-muted-foreground md:text-base">
{section.subTitle}
</p>
<h1 className="text-xl font-semibold md:text-xl">
{section.title}
</h1>
<p className="text-muted-foreground">{section.description}</p>
</div>
))}
</div>
<div className="sticky top-56 start-0 hidden h-fit w-full items-center justify-center md:flex">
<img
src={sections[sections.length - 1].image}
alt={sections[sections.length - 1].title}
className="invisible h-full max-h-[550px] w-full max-w-full object-cover"
/>
{sections.map((item, index) => (
<div
key={index}
className={cn(
"absolute inset-0 flex h-full items-center justify-center rounded-2xl border bg-muted p-4 transition-opacity duration-200",
index === activeIndex ? "opacity-100" : "opacity-0",
)}
>
<img
src={item.image}
alt={item.title}
className="h-full max-h-full w-full max-w-full rounded-2xl border object-cover"
/>
</div>
))}
</div>
</div>
</div>
</section>
);
};
export { Timeline2 };