150 lines
6.2 KiB
TypeScript
150 lines
6.2 KiB
TypeScript
"use client";
|
|
|
|
import { AnimatePresence, motion } from "framer-motion";
|
|
import Image from "next/image";
|
|
import { useMemo, useState } from "react";
|
|
|
|
import { ScrollableTabsList } from "@/components/shadcnblocks/scrollable-tabslist";
|
|
import { ScrollBar } from "@/components/ui/scroll-area";
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface FeatureWorkspaceTabsProps {
|
|
className?: string;
|
|
}
|
|
|
|
const tabItems = [
|
|
{
|
|
value: "display",
|
|
label: "نمایش حرفهای",
|
|
eyebrow: "ویترین و استند",
|
|
title: "ویترینی بسازید که فروش را سریع تر می کند",
|
|
description:
|
|
"چیدمان اصولی استندها باعث می شود سرویس های طلا و جواهر بهتر دیده شوند، تصمیم خرید سریع تر گرفته شود ",
|
|
image: "/assets/main-pic/feature/feature1.webp",
|
|
stats: [
|
|
{ value: "۳۵۰+", label: "پروژه اجراشده در فروشگاه" },
|
|
{ value: "۱۵+", label: "سال تجربه در دکور طلافروشی" },
|
|
],
|
|
},
|
|
{
|
|
value: "identity",
|
|
label: "هماهنگ با برند",
|
|
eyebrow: "دکور مجموعه شما",
|
|
title: "دکور هماهنگ با هویت برند طلافروشی شما",
|
|
description:
|
|
"روکش، متریال و جزئیات اجرایی را بر اساس سبک فروشگاه شما انتخاب می کنیم تا هر استند بخشی از هویت برندتان باشد و در ذهن مشتری ماندگار بماند.",
|
|
image: "/assets/main-pic/feature/feature1.webp",
|
|
stats: [
|
|
{ value: "۹۳٪", label: "رضایت مشتریان در نظرسنجیها" },
|
|
{ value: "۴۸ ساعت", label: "شروع پشتیبانی پس از تحویل" },
|
|
],
|
|
},
|
|
{
|
|
value: "lifecycle",
|
|
label: "از مشاوره تا پس از فروش",
|
|
eyebrow: "همراهی مستر دکور",
|
|
title: "از مشاوره تا نصب، یک مسیر شفاف و قابل اتکا",
|
|
description:
|
|
"از بازدید و نیازسنجی تا تولید و نصب، برنامه زمان بندی مشخص ارائه می کنیم و بعد از تحویل نیز با خدمات پس از فروش کنار شما می مانیم .",
|
|
image: "/assets/main-pic/feature/feature1.webp",
|
|
stats: [
|
|
{ value: "۱۰۰٪", label: "هماهنگی با ابعاد واقعی فضا" },
|
|
{ value: "گارانتی", label: "تعهد کیفی روی اجرای سازه" },
|
|
],
|
|
},
|
|
];
|
|
|
|
const FeatureWorkspaceTabs = ({ className }: FeatureWorkspaceTabsProps) => {
|
|
const [activeTab, setActiveTab] = useState("display");
|
|
const activeItem = useMemo(
|
|
() => tabItems.find((item) => item.value === activeTab) ?? tabItems[0],
|
|
[activeTab],
|
|
);
|
|
|
|
return (
|
|
<section className={cn("section-blur-separator py-20 md:py-28", className)} dir="rtl">
|
|
<div className="mx-auto flex w-full max-w-7xl justify-center px-4 sm:px-6">
|
|
<Tabs
|
|
value={activeTab}
|
|
onValueChange={setActiveTab}
|
|
defaultValue="display"
|
|
className="mx-auto grid w-full max-w-6xl grid-cols-1 gap-8 lg:grid-cols-2 lg:items-center xl:gap-20"
|
|
>
|
|
<div className="flex flex-col-reverse items-center justify-between gap-8 text-center lg:flex-col lg:text-center">
|
|
<div>
|
|
<AnimatePresence mode="wait" initial={false}>
|
|
<motion.div
|
|
key={activeItem.value}
|
|
initial={{ opacity: 0, y: 12 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: -10 }}
|
|
transition={{ duration: 0.35, ease: "easeOut" }}
|
|
>
|
|
<TabsContent
|
|
value={activeItem.value}
|
|
forceMount
|
|
className="mt-0 flex flex-col items-center gap-6"
|
|
>
|
|
<span className="text-caption font-medium text-muted-foreground">
|
|
{activeItem.eyebrow}
|
|
</span>
|
|
<div className="flex max-w-xl flex-col gap-4">
|
|
<h2 className="text-heading-2 font-semibold text-foreground">
|
|
{activeItem.title}
|
|
</h2>
|
|
<div className="tone-gradient-line" aria-hidden />
|
|
<p className="text-body text-muted-foreground">{activeItem.description}</p>
|
|
</div>
|
|
</TabsContent>
|
|
</motion.div>
|
|
</AnimatePresence>
|
|
</div>
|
|
|
|
<ScrollableTabsList className="w-full">
|
|
<TabsList className="mx-auto h-12 overflow-y-hidden rounded-full">
|
|
{tabItems.map((item) => (
|
|
<TabsTrigger
|
|
key={item.value}
|
|
value={item.value}
|
|
className="h-full rounded-full px-4 py-2 transition-all duration-300"
|
|
>
|
|
{item.label}
|
|
</TabsTrigger>
|
|
))}
|
|
</TabsList>
|
|
<ScrollBar orientation="horizontal" className="h-2" />
|
|
</ScrollableTabsList>
|
|
</div>
|
|
|
|
<div className="relative">
|
|
<AnimatePresence mode="wait" initial={false}>
|
|
<motion.div
|
|
key={activeItem.value}
|
|
initial={{ opacity: 0, scale: 0.985 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
exit={{ opacity: 0, scale: 1.01 }}
|
|
transition={{ duration: 0.4, ease: "easeOut" }}
|
|
>
|
|
<TabsContent value={activeItem.value} forceMount className="mt-0">
|
|
<div className="relative overflow-hidden rounded-3xl">
|
|
<Image
|
|
src={activeItem.image}
|
|
alt={activeItem.title}
|
|
width={1200}
|
|
height={900}
|
|
className="h-[440px] w-full object-cover lg:h-[540px]"
|
|
/>
|
|
</div>
|
|
</TabsContent>
|
|
</motion.div>
|
|
</AnimatePresence>
|
|
</div>
|
|
</Tabs>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { FeatureWorkspaceTabs };
|