خدمات با قیمتِ شروع
پیشنمایش تمامصفحهبخشِ خدمات در کارتهای عکسدار با قیمتِ «از»، مدتِ تحویل، اقلامِ بسته و دکمهٔ پیشفاکتور؛ برای استودیو و فریلنسر.
۱. نصب کامپوننتها
این بلاک از ۵ آیتم دیگ استفاده میکند: buttoncontrol-sizeiconspersianreveal
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
services-cards.tsx
"use client"
import { CheckIcon } from "@/components/icons"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Reveal } from "@/components/ui/reveal"
import { formatCurrency, toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"
const SERVICES: { title: string; text: string; from: number; days: number; points: string[]; photo: StockImageName }[] = [
{
title: "عکاسیِ محصول",
text: "عکسِ سفید و صحنهپردازیشده برای فروشگاهِ آنلاین.",
from: 4_500_000,
days: 3,
points: ["۲۰ عکسِ ویرایششده", "پسزمینهٔ سفید و صحنه", "فایلِ مخصوصِ موبایل"],
photo: "productVase",
},
{
title: "هویتِ بصری",
text: "نشانه، رنگ و حروف، با راهنمای استفاده.",
from: 18_000_000,
days: 14,
points: ["سه پیشنهادِ اولیه", "دو دورِ بازبینی", "کتابچهٔ برند"],
photo: "projectCafeBrand",
},
{
title: "طراحیِ اپ",
text: "از نقشهٔ صفحه تا نمونهٔ قابلِ کلیک.",
from: 42_000_000,
days: 30,
points: ["پژوهشِ کاربر", "طراحیِ ۲۵ صفحه", "تحویل به تیمِ فنی"],
photo: "projectMobileApp",
},
]
/**
* خدمات در کارتهای عکسدار با قیمتِ شروع: عکس بالای کارت، تیتر و توضیح، قیمتِ «از» و مدتِ
* تحویل، سه مورد از آنچه در بسته هست و دکمهٔ درخواست؛ برای استودیو و فریلنسر.
*/
export default function ServicesCardsBlock() {
return (
<ControlSizeProvider size="xl" asChild>
<section aria-labelledby="sc-title" className="w-full bg-subtle py-24">
<div className="mx-auto flex w-full max-w-6xl flex-col gap-12 px-4 sm:px-6">
<div className="mx-auto flex max-w-2xl flex-col items-center gap-3 text-center">
<span className="text-sm font-semibold text-brand-secondary">خدماتِ استودیو</span>
<h2 id="sc-title" className="text-3xl leading-snug font-black text-balance sm:text-4xl">
قیمتِ روشن، تحویلِ سرِ وقت
</h2>
</div>
<ul className="grid grid-cols-1 gap-6 md:grid-cols-3">
{SERVICES.map((service, index) => (
<Reveal asChild key={service.title} delay={index * 100}>
<li className="flex flex-col overflow-hidden rounded-xl bg-card shadow-sm">
{/* eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ */}
<img src={stockImages[service.photo].src} alt="" className="aspect-[16/10] w-full object-cover" />
<div className="flex flex-1 flex-col gap-5 p-6">
<div className="flex flex-col gap-1.5">
<h3 className="text-xl font-bold">{service.title}</h3>
<p className="leading-7 text-muted-foreground">{service.text}</p>
</div>
<div className="flex items-baseline justify-between gap-2 border-y border-border py-4">
<span className="flex items-baseline gap-1.5">
<span className="text-sm text-muted-foreground">از</span>
<span className="text-xl font-black tabular-nums">{formatCurrency(service.from)}</span>
</span>
<span className="text-sm text-muted-foreground">{toFaDigits(service.days)} روزِ کاری</span>
</div>
<ul className="flex flex-col gap-2.5">
{service.points.map((point) => (
<li key={point} className="flex items-center gap-2.5 text-sm">
<span aria-hidden className="flex size-5 items-center justify-center rounded-full bg-success-subtle text-success">
<CheckIcon className="size-3.5" />
</span>
{point}
</li>
))}
</ul>
<Button variant={index === 1 ? "default" : "outline"} className="mt-auto" fullWidth>
درخواستِ پیشفاکتور
</Button>
</div>
</li>
</Reveal>
))}
</ul>
</div>
</section>
</ControlSizeProvider>
)
}