مراحل با کارتِ عکس
پیشنمایش تمامصفحهبخشِ روندِ کار در چهار کارتِ عکسدارِ عمودی با شمارهٔ قدم، تیتر و یک جمله؛ در موبایل ریلِ افقی.
۱. نصب کامپوننتها
این بلاک از ۳ آیتم دیگ استفاده میکند: control-sizepersianreveal
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
process-cards.tsx
"use client"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Reveal } from "@/components/ui/reveal"
import { toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"
const STEPS: { title: string; text: string; photo: StockImageName }[] = [
{ title: "مشاورهٔ مصرف", text: "قبضهای یک سال را میخوانیم و نیازِ واقعیِ خانه را میسنجیم.", photo: "coverCalculator" },
{ title: "طراحیِ سفارشی", text: "چیدمانِ پنلها را برای بیشترین نورِ بامِ شما طراحی میکنیم.", photo: "projectDashboard" },
{ title: "نصبِ حرفهای", text: "تیمِ دارای گواهی در یک روز نصب را تمام و تحویل میدهد.", photo: "studioSunlit" },
{ title: "روشنکردن و پایش", text: "از همان شب تولیدِ برق را لحظهبهلحظه در اپ میبینید.", photo: "projectMobileApp" },
]
/**
* روندِ کار در چهار کارتِ عکسدار: هر کارت عکسِ عمودی با شمارهٔ قدم روی آن، تیتر و یک
* جمله؛ کارتها پلهپله وارد میشوند و در موبایل ریلِ افقیِ قابلِ کشیدناند.
*/
export default function ProcessCardsBlock() {
return (
<ControlSizeProvider size="xl" asChild>
<section aria-labelledby="pc-title" className="mx-auto flex w-full max-w-6xl flex-col gap-12 py-24">
<div className="mx-auto flex max-w-2xl flex-col items-center gap-3 px-4 text-center sm:px-6">
<span className="rounded-full border border-border px-3 py-1 text-sm font-semibold">چطور کار میکند</span>
<h2 id="pc-title" className="text-3xl leading-snug font-black text-balance sm:text-4xl">
برنامهریزیِ ما، برقِ خانهٔ شما
</h2>
</div>
<ol className="flex snap-x snap-mandatory gap-4 overflow-x-auto px-4 pb-2 [scrollbar-width:none] sm:px-6 md:grid md:grid-cols-4 md:overflow-visible [&::-webkit-scrollbar]:hidden">
{STEPS.map((step, index) => (
<Reveal asChild key={step.title} delay={index * 100}>
<li className="group flex w-64 shrink-0 snap-start flex-col gap-4 md:w-auto">
<div className="relative overflow-hidden rounded-xl">
{/* eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ */}
<img src={stockImages[step.photo].src} alt="" className="aspect-[4/5] w-full object-cover transition-transform duration-700 group-hover:scale-105" />
<span className="absolute start-3 top-3 rounded-full bg-card px-3 py-1 text-sm font-bold tabular-nums shadow-sm">{toFaDigits(String(index + 1).padStart(2, "0"))}</span>
</div>
<div className="flex flex-col gap-1.5">
<h3 className="text-lg font-bold">{step.title}</h3>
<p className="text-sm leading-6 text-muted-foreground">{step.text}</p>
</div>
</li>
</Reveal>
))}
</ol>
</section>
</ControlSizeProvider>
)
}