بلاک‌ها · فروشگاهی

جزئیاتِ کالا با گالریِ عمودی

پیش‌نمایش تمام‌صفحه

عکس‌های بزرگِ کالا زیرِ هم و ستونِ اطلاعاتِ چسبان: نام، امتیاز، قیمت، رنگ با دایره، سبد و پسند، ارسال و ضمانت و جزئیات در آکاردئون.

۱. نصب کامپوننت‌ها

این بلاک از ۷ آیتم دیگ استفاده می‌کند: 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.json
pnpm 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.json
yarn 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.json
bunx --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>
  )
}