180 lines
7.2 KiB
TypeScript
180 lines
7.2 KiB
TypeScript
"use client";
|
|
|
|
import { motion, useScroll, useTransform } from "framer-motion";
|
|
import { Cpu, LayoutList, LocateFixed, Rocket, Users } from "lucide-react";
|
|
import { useRef } from "react";
|
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const DATA = [
|
|
{
|
|
title: "سازماندهی کنید",
|
|
description:
|
|
"از همان ابتدا قوی شروع کنید؛ تقویمها و ابزارهایی مثل حساب ابری Calendar، مدیریت وظایف و پیامرسان تیمی را در یک جا همگام کنید.",
|
|
icon: LayoutList,
|
|
image: {
|
|
src: "/block-media/shadcnblocks/block/placeholder-1.svg",
|
|
alt: "سازماندهی",
|
|
},
|
|
},
|
|
{
|
|
title: "پیگیری پیشرفت",
|
|
description:
|
|
"عملکرد خود را با داشبوردهای لحظهای و تحلیلهای دقیق پایش کنید. با گزارشهای خودکار همیشه جلوتر باشید.",
|
|
icon: LocateFixed,
|
|
image: {
|
|
src: "/block-media/shadcnblocks/block/placeholder-2.svg",
|
|
alt: "پیگیری پیشرفت",
|
|
},
|
|
reverse: true,
|
|
},
|
|
{
|
|
title: "همکاری بینقص",
|
|
description:
|
|
"تیم خود را با داشبوردهای مشترک و ابزارهای ارتباطی فوری توانمند کنید. همه را با پلتفرمهای یکپارچه همراستا نگه دارید.",
|
|
icon: Users,
|
|
image: {
|
|
src: "/block-media/shadcnblocks/block/placeholder-3.svg",
|
|
alt: "همکاری بینقص",
|
|
},
|
|
},
|
|
{
|
|
title: "یکپارچهسازی بیدرز",
|
|
description:
|
|
"در چند پلتفرم بهصورت یکپارچه متصل شوید تا واگذاری وظایف روان و خودکار فراهم شود.",
|
|
icon: Cpu,
|
|
image: {
|
|
src: "/block-media/shadcnblocks/block/placeholder-4.svg",
|
|
alt: "یکپارچهسازی بیدرز",
|
|
},
|
|
reverse: true,
|
|
},
|
|
];
|
|
|
|
const Timeline4 = () => {
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
const { scrollYProgress } = useScroll({
|
|
target: ref,
|
|
offset: ["start center", "end center"],
|
|
});
|
|
const height = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
|
|
|
|
return (
|
|
<section dir="rtl" lang="fa" className="py-32">
|
|
<div className="border-y">
|
|
<div className="container flex flex-col gap-6 border-x py-4 text-start max-lg:border-x lg:py-8">
|
|
<Badge
|
|
variant="outline"
|
|
className="w-fit gap-1 bg-card px-3 text-sm font-normal tracking-tight shadow-sm"
|
|
>
|
|
<Rocket className="size-4" />
|
|
<span>تسریع</span>
|
|
</Badge>
|
|
<h2 className="text-3xl leading-tight tracking-tight md:text-xl lg:text-2xll">
|
|
سفر برنامهریزی خود را تسریع کنید
|
|
</h2>
|
|
<p className="max-w-[600px] tracking-[-0.32px] text-muted-foreground">
|
|
گردش کار خود را گامبهگام با ابزارهای هوشمند، بینشهای عملی و
|
|
همکاری بیدرز کنترل کنید
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
ref={ref}
|
|
className="relative container border-x pb-40 lg:pt-20 [&>*:last-child]:pb-20 [&>div>div:first-child]:pt-20!"
|
|
>
|
|
<div className="pointer-events-none absolute top-0 z-0 h-full w-[3px] max-lg:-translate-x-5 lg:left-1/2 lg:-translate-x-1/2">
|
|
<div className="h-4 w-[3px] bg-linear-to-b from-transparent to-foreground/10"></div>
|
|
<div className="relative h-[calc(100%-1rem)] w-full bg-linear-to-b from-foreground/10 via-foreground/10 to-transparent">
|
|
<motion.div
|
|
className="absolute top-0 left-0 z-10 w-[3px] rounded-full bg-linear-to-b from-transparent via-foreground to-transparent"
|
|
style={{ height }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
{DATA.map((item, index) => (
|
|
<div key={index} className="relative flex">
|
|
<div
|
|
className={`flex w-full justify-center px-1 py-10 text-end md:gap-6 lg:gap-10 ${item?.reverse ? "lg:flex-row-reverse lg:text-start" : ""} `}
|
|
>
|
|
<div className="flex-1 max-lg:hidden">
|
|
<h3 className="text-xl tracking-[-0.96px]">{item.title}</h3>
|
|
<p
|
|
className={`mt-2.5 max-w-[300px] tracking-[-0.32px] text-balance text-muted-foreground ${item?.reverse ? "" : "ms-auto"}`}
|
|
>
|
|
{item.description}
|
|
</p>
|
|
</div>
|
|
<div className="z-[-1] size-fit -translate-y-5 bg-background p-4 max-lg:translate-x-4">
|
|
<div className="rounded-[10px] border bg-card p-[5px] shadow-md">
|
|
<div className="size-fit rounded-md border bg-muted p-1">
|
|
<item.icon className="size-4 shrink-0" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex-1 max-lg:translate-x-4">
|
|
<div className="text-start lg:pointer-events-none lg:hidden">
|
|
<h3 className="text-xl tracking-[-0.96px]">{item.title}</h3>
|
|
<p className="mt-2.5 mb-10 max-w-[300px] tracking-[-0.32px] text-balance text-muted-foreground">
|
|
{item.description}
|
|
</p>
|
|
</div>
|
|
<div className="flex items-start justify-start">
|
|
<div className={` ${item?.reverse ? "lg:ms-auto" : ""}`}>
|
|
<div className="px-6 lg:px-10">
|
|
<DiagonalPattern className="h-6 lg:h-10" />
|
|
</div>
|
|
<div className="relative grid grid-cols-[auto_1fr_auto] items-stretch">
|
|
<DiagonalPattern className="h-full w-6 lg:w-10" />
|
|
<img
|
|
src={item.image.src}
|
|
width={400}
|
|
height={500}
|
|
alt={item.image.alt}
|
|
className="object-contain dark:invert"
|
|
/>
|
|
<DiagonalPattern className="w-6 lg:w-10" />
|
|
</div>
|
|
<div className="px-6 lg:px-10">
|
|
<DiagonalPattern className="h-6 lg:h-10" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="h-8 w-full border-y md:h-12 lg:h-[112px]">
|
|
<div className="container h-full w-full border-x"></div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Timeline4 };
|
|
|
|
const DiagonalPattern = ({
|
|
className,
|
|
patternColor = "hsl(var(--foreground))",
|
|
patternOpacity = 0.15,
|
|
}: {
|
|
className?: string;
|
|
patternColor?: string;
|
|
patternOpacity?: number;
|
|
}) => {
|
|
const svgPattern = `url("data:image/svg+xml,%3Csvg width='7' height='7' viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23${patternColor}' fill-opacity='${patternOpacity}' fill-rule='evenodd'%3E%3Cpath d='M5 0h1L0 6V5zM6 5v1H5z'/%3E%3C/g%3E%3C/svg%3E")`;
|
|
|
|
return (
|
|
<div
|
|
className={cn("h-full w-full border-2 border-dashed", className)}
|
|
style={{
|
|
backgroundImage: svgPattern,
|
|
}}
|
|
/>
|
|
);
|
|
};
|