Build & Push Docker Image / build (push) Has been cancelled
Refresh the homepage around new hero/services/roadmap sections, shared design tokens, and updated brand assets. Co-authored-by: Cursor <cursoragent@cursor.com>
201 lines
8.5 KiB
TypeScript
201 lines
8.5 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
|
|
import {
|
|
Accordion,
|
|
AccordionContent,
|
|
AccordionItem,
|
|
AccordionTrigger,
|
|
} from "@/components/ui/accordion";
|
|
import { Container } from "@/components/container";
|
|
import { MotionReveal, MotionRevealItem } from "@/components/motion-reveal";
|
|
import { BorderBeam } from "@/components/ui/border-beam";
|
|
import { layout } from "@/lib/layout";
|
|
import { type } from "@/lib/typography";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface FeatureItem {
|
|
id: number;
|
|
title: string;
|
|
image: string;
|
|
description: string[];
|
|
}
|
|
|
|
interface Feature197Props {
|
|
features?: FeatureItem[];
|
|
className?: string;
|
|
}
|
|
|
|
const defaultFeatures: FeatureItem[] = [
|
|
{
|
|
id: 1,
|
|
title: "به صرفه",
|
|
image: "/assets/main-pic/55.jpg",
|
|
description: [
|
|
"داشتن وبسایت حرفهای نباید هزینههای سنگین داشته باشد. ما بستههای متنوع و اقتصادی متناسب با بودجه هر کسبوکار ارائه میدهیم تا با سرمایهگذاری منطقی، حضوری قوی و قابلاعتماد در فضای آنلاین داشته باشید.",
|
|
],
|
|
},
|
|
{
|
|
id: 2,
|
|
title: "دانش بالا",
|
|
image: "/assets/main-pic/66.jpg",
|
|
description: [
|
|
"تیم ما متشکل از طراحان، برنامهنویسان و متخصصان سئو است که با استانداردهای روز وب کار میکنند. هدفمان ساخت سایتی سریع، امن و کاربرپسند است که به رشد برند و جذب مشتری کمک کند.",
|
|
],
|
|
},
|
|
{
|
|
id: 3,
|
|
title: "رضایت مشتری",
|
|
image: "/assets/main-pic/77.jpg",
|
|
description: [
|
|
"از ابتدای پروژه تا پس از تحویل، شفاف و منظم کنار شما هستیم. نیازها و انتظاراتتان را دقیق بررسی میکنیم و با پشتیبانی متعهدانه، تجربهای مطمئن و نتیجهمحور برای رشد کسبوکارتان میسازیم.",
|
|
],
|
|
},
|
|
{
|
|
id: 4,
|
|
title: "سریع و باکیفیت",
|
|
image: "/assets/main-pic/88.jpg",
|
|
description: [
|
|
"پروژه را در کوتاهترین زمان ممکن و بدون افت کیفیت تحویل میدهیم. از ظاهر کاربرپسند تا کدنویسی استاندارد و سئو، دقت در جزئیات برای ما اصل غیرقابل مذاکره است.",
|
|
],
|
|
},
|
|
{
|
|
id: 5,
|
|
title: "تجربه بالا",
|
|
image: "/assets/main-pic/99.jpg",
|
|
description: [
|
|
"سالها همکاری با کسبوکارهای متنوع به ما کمک کرده نیاز هر صنعت را درست بشناسیم و از اشتباهات رایج جلوگیری کنیم. این سابقه، از مشاوره تا تحویل نهایی، کیفیت و اطمینان پروژه را تضمین میکند.",
|
|
],
|
|
},
|
|
];
|
|
|
|
export function Feature197({
|
|
features = defaultFeatures,
|
|
className,
|
|
}: Feature197Props) {
|
|
const [activeTabId, setActiveTabId] = useState<number | null>(features[0]?.id ?? 1);
|
|
const [activeImage, setActiveImage] = useState(features[0]?.image ?? "");
|
|
|
|
return (
|
|
<section
|
|
className={cn(
|
|
"section-shell bg-section-lift",
|
|
layout.scrollMargin,
|
|
layout.sectionY,
|
|
className
|
|
)}
|
|
>
|
|
<Container className="section-content">
|
|
<MotionReveal stagger>
|
|
<MotionRevealItem>
|
|
<h2 className={cn(type.h2, "mb-12")}>چرا امین رایان؟</h2>
|
|
</MotionRevealItem>
|
|
<MotionRevealItem>
|
|
<div className="flex w-full flex-col items-start justify-between gap-10 md:gap-12 lg:flex-row">
|
|
<div className="w-full min-w-0 lg:w-1/2">
|
|
<Accordion
|
|
type="single"
|
|
collapsible
|
|
className={cn(
|
|
"w-full",
|
|
// Soften default 200ms accordion height motion for this section
|
|
"[&_[data-slot=accordion-content][data-state=open]]:[animation-duration:560ms]",
|
|
"[&_[data-slot=accordion-content][data-state=closed]]:[animation-duration:440ms]",
|
|
"[&_[data-slot=accordion-content]]:[animation-timing-function:cubic-bezier(0.22,1,0.36,1)]"
|
|
)}
|
|
defaultValue={`item-${features[0]?.id ?? 1}`}
|
|
>
|
|
{features.map((tab) => (
|
|
<AccordionItem
|
|
key={tab.id}
|
|
value={`item-${tab.id}`}
|
|
className="transition-opacity duration-300 hover:opacity-80"
|
|
>
|
|
<AccordionTrigger
|
|
onClick={() => {
|
|
setActiveImage(tab.image);
|
|
setActiveTabId(tab.id);
|
|
}}
|
|
className="cursor-pointer py-4 no-underline! transition-colors duration-300 hover:no-underline sm:py-5 [&[data-state=open]>svg]:duration-500 [&>svg]:transition-transform [&>svg]:duration-500"
|
|
>
|
|
<h3
|
|
className={cn(
|
|
type.h3,
|
|
"transition-colors duration-500 ease-out",
|
|
tab.id === activeTabId
|
|
? "text-foreground"
|
|
: "text-muted-foreground"
|
|
)}
|
|
>
|
|
{tab.title}
|
|
</h3>
|
|
</AccordionTrigger>
|
|
<AccordionContent className="pb-2">
|
|
<div
|
|
className={cn(
|
|
type.body,
|
|
"flex flex-col gap-3 text-muted-foreground",
|
|
"animate-in fade-in-0 slide-in-from-top-1 duration-500 ease-out fill-mode-both"
|
|
)}
|
|
>
|
|
{tab.description.map((paragraph, index) => (
|
|
<p key={`${tab.id}-${index}`}>{paragraph}</p>
|
|
))}
|
|
</div>
|
|
<div className="media-frame relative mt-4 overflow-hidden rounded-xl lg:hidden">
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img
|
|
src={tab.image}
|
|
alt={tab.title}
|
|
className="h-full max-h-64 w-full rounded-[inherit] object-cover animate-in fade-in-0 zoom-in-[0.985] duration-700 ease-out fill-mode-both sm:max-h-80"
|
|
/>
|
|
<BorderBeam
|
|
duration={6}
|
|
size={160}
|
|
borderWidth={1}
|
|
colorFrom="#29A19C"
|
|
colorTo="#044343"
|
|
/>
|
|
</div>
|
|
</AccordionContent>
|
|
</AccordionItem>
|
|
))}
|
|
</Accordion>
|
|
</div>
|
|
<div className="relative hidden w-1/2 min-w-0 lg:block">
|
|
<div className="local-highlight local-highlight--soft" aria-hidden />
|
|
<div className="media-frame relative z-[1] rounded-xl bg-muted/40">
|
|
<div className="relative aspect-4/3 overflow-hidden rounded-[inherit]">
|
|
{features.map((feature) => (
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
<img
|
|
key={feature.id}
|
|
src={feature.image}
|
|
alt={feature.title}
|
|
className={cn(
|
|
"absolute inset-0 size-full object-cover transition-opacity duration-700 ease-out",
|
|
activeImage === feature.image
|
|
? "opacity-100"
|
|
: "opacity-0"
|
|
)}
|
|
/>
|
|
))}
|
|
</div>
|
|
<BorderBeam
|
|
duration={6}
|
|
size={200}
|
|
borderWidth={1}
|
|
colorFrom="#29A19C"
|
|
colorTo="#044343"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</MotionRevealItem>
|
|
</MotionReveal>
|
|
</Container>
|
|
</section>
|
|
);
|
|
}
|