جزئیاتِ کالا با گالریِ عمودی
پیشنمایش تمامصفحهعکسهای بزرگِ کالا زیرِ هم و ستونِ اطلاعاتِ چسبان: نام، امتیاز، قیمت، رنگ با دایره، سبد و پسند، ارسال و ضمانت و جزئیات در آکاردئون.
۱. نصب کامپوننتها
این بلاک از ۷ آیتم دیگ استفاده میکند: accordionadd-to-cartbuttoncolor-swatch-pickercontrol-sizeiconspersian
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/add-to-cart.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/color-swatch-picker.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/add-to-cart.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/color-swatch-picker.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/add-to-cart.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/color-swatch-picker.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/add-to-cart.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/color-swatch-picker.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
product-detail-gallery.tsx
"use client"
import * as React from "react"
import { HeartIcon, ShieldCheckIcon, StarIcon, TruckIcon } from "@/components/icons"
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { AddToCart } from "@/components/ui/add-to-cart"
import { Button } from "@/components/ui/button"
import { ColorSwatchPicker, ColorSwatchPickerItem } from "@/components/ui/color-swatch-picker"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { formatCurrency } from "@/lib/persian"
import { stockImages } from "@/lib/stock-images"
const PHOTOS = [stockImages.productVase, stockImages.coverMinimalRoom, stockImages.studioSunlit]
const COLORS = [
{ value: "cream", label: "کرم", swatch: "var(--dig-orange-100)" },
{ value: "olive", label: "سبزِ زیتونی", swatch: "var(--dig-green-700)" },
{ value: "navy", label: "سرمهای", swatch: "var(--dig-blue-900)" },
]
/**
* جزئیاتِ کالا با گالری عمودی: عکسهای بزرگ زیرِ هم در یک ستون و ستونِ اطلاعاتِ چسبان
* کنارش (نام، امتیاز، قیمت، رنگ با دایره، سبد و پسند، ارسال و ضمانت، جزئیات در آکاردئون).
* برای کالاهایی که عکس فروشندهشان است: لباس، دکور، صنایعدستی.
*/
export default function ProductDetailGalleryBlock() {
const [color, setColor] = React.useState(COLORS[0].value)
const [liked, setLiked] = React.useState(false)
return (
<ControlSizeProvider size="xl" asChild>
<main className="mx-auto grid w-full max-w-6xl grid-cols-1 items-start gap-10 p-4 sm:p-6 lg:grid-cols-[minmax(0,1.3fr)_minmax(0,1fr)]">
<div className="flex flex-col gap-4">
{PHOTOS.map((photo, index) => (
// eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ
<img key={photo.src} src={photo.src} alt={index === 0 ? photo.alt : ""} loading={index === 0 ? undefined : "lazy"} className="aspect-[4/5] w-full rounded-xl object-cover" />
))}
</div>
<section className="flex flex-col gap-6 lg:sticky lg:top-6">
<div className="flex flex-col gap-2">
<a href="#" className="text-sm text-muted-foreground hover:underline">
خانهٔ سفال
</a>
<h1 className="text-3xl font-bold">گلدانِ سرامیکی دوقلو</h1>
<span className="flex items-center gap-1.5 text-sm">
<StarIcon aria-hidden className="size-4 fill-[var(--dig-orange-400)] text-[var(--dig-orange-400)]" />
۴٫۸ <a href="#" className="text-muted-foreground hover:underline">(۲۱۲ نظر)</a>
</span>
</div>
<span className="text-3xl font-black tabular-nums">{formatCurrency(1_290_000)}</span>
<div className="flex flex-col gap-3">
<span id="pdg-color" className="text-sm font-medium">
رنگ: {COLORS.find((item) => item.value === color)?.label}
</span>
<ColorSwatchPicker value={color} onValueChange={setColor} aria-labelledby="pdg-color" size="lg" radius="full" indicator="ring" className="gap-4 p-1">
{COLORS.map((item) => (
<ColorSwatchPickerItem key={item.value} value={item.value} color={item.swatch} label={item.label} />
))}
</ColorSwatchPicker>
</div>
<div className="flex gap-3 pt-2">
<AddToCart variant="default" fullWidth itemName="کالا" className="flex-1" />
<Button variant="outline" size="icon" aria-label={liked ? "حذف از علاقهمندیها" : "افزودن به علاقهمندیها"} aria-pressed={liked} onClick={() => setLiked((value) => !value)} className={liked ? "text-destructive" : ""}>
<HeartIcon filled={liked} />
</Button>
</div>
<ul className="flex flex-col gap-3 rounded-xl bg-subtle p-4 text-sm">
<li className="flex items-center gap-3">
<TruckIcon aria-hidden className="size-5 text-brand-secondary" />
ارسالِ فردا؛ رایگان برای خریدِ بالای ۳ میلیون
</li>
<li className="flex items-center gap-3">
<ShieldCheckIcon aria-hidden className="size-5 text-brand-secondary" />
ضمانتِ سالمرسیدن و ۷ روز بازگشت
</li>
</ul>
<Accordion type="single" collapsible defaultValue="about">
<AccordionItem value="about">
<AccordionTrigger>دربارهٔ کالا</AccordionTrigger>
<AccordionContent className="leading-8 text-muted-foreground">دستسازِ کارگاهِ لالجین با لعابِ مات؛ مناسبِ گلِ طبیعی و خشک. هر تکه کمی با دیگری فرق دارد.</AccordionContent>
</AccordionItem>
<AccordionItem value="size">
<AccordionTrigger>ابعاد و جنس</AccordionTrigger>
<AccordionContent className="leading-8 text-muted-foreground">ارتفاعِ ۳۲ و قطرِ ۱۴ سانتیمتر؛ سرامیکِ پخته در ۱۲۰۰ درجه.</AccordionContent>
</AccordionItem>
<AccordionItem value="care">
<AccordionTrigger>نگهداری</AccordionTrigger>
<AccordionContent className="leading-8 text-muted-foreground">با دستمالِ نمدار تمیز شود؛ در ماشینِ ظرفشویی نگذارید.</AccordionContent>
</AccordionItem>
</Accordion>
</section>
</main>
</ControlSizeProvider>
)
}