بلاک‌ها · معرفی محصول

قیمت‌گذاری، تیره و رنگ‌کد

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

قیمت‌گذاری روی صفحهٔ تیره: هر پلن نوارِ رنگیِ خودش را دارد و پلنِ پیشنهادی درخشش و قابِ روشن؛ سوییچِ ماهانه/سالانه، فهرستِ دارد/ندارد و ردیفِ سازمانی با تماس با فروش.

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

این بلاک از ۵ آیتم دیگ استفاده می‌کند: buttoncontrol-sizeiconsrevealtoggle-group

پکیج‌منیجر پیش‌فرض 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/reveal.json https://docs.digdesign.ir/r/toggle-group.json
pnpm 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/reveal.json https://docs.digdesign.ir/r/toggle-group.json
yarn 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/reveal.json https://docs.digdesign.ir/r/toggle-group.json
bunx --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/reveal.json https://docs.digdesign.ir/r/toggle-group.json

۲. کد صفحه

کد را در app/<route>/page.tsx بگذارید و متن‌ها، داده و هندلرها را با محصول خودتان عوض کنید.

pricing-dark.tsx
"use client"

import * as React from "react"

import { ArrowUpIcon, CheckIcon, MinusIcon } from "@/components/icons"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Reveal } from "@/components/ui/reveal"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { cn } from "@/lib/utils"

const PLANS = [
  {
    name: "پایه",
    text: "برای فریلنسرها و پروژه‌های شخصی",
    month: 0,
    band: "bg-[var(--dig-cyan-400)]",
    accent: "text-[var(--dig-cyan-300)]",
    features: [["۳ پروژه", true], ["۱ گیگابایت فضا", true], ["دامنهٔ اختصاصی", false], ["گزارشِ پیشرفته", false]],
  },
  {
    name: "رشد",
    text: "برای تیم‌های کوچکِ در حالِ رشد",
    month: 390,
    band: "bg-[linear-gradient(90deg,var(--dig-violet-500),var(--dig-pink-500))]",
    accent: "text-[var(--dig-violet-300)]",
    featured: true,
    features: [["پروژهٔ نامحدود", true], ["۵۰ گیگابایت فضا", true], ["دامنهٔ اختصاصی", true], ["گزارشِ پیشرفته", false]],
  },
  {
    name: "حرفه‌ای",
    text: "برای کسب‌وکارهایی با ترافیکِ بالا",
    month: 990,
    band: "bg-[var(--dig-orange-400)]",
    accent: "text-[var(--dig-orange-300)]",
    features: [["پروژهٔ نامحدود", true], ["۵۰۰ گیگابایت فضا", true], ["دامنهٔ اختصاصی", true], ["گزارشِ پیشرفته", true]],
  },
] as const

/**
 * قیمت‌گذاری روی صفحهٔ تیره با پلن‌های رنگ‌کد: هر پلن نوارِ رنگیِ خودش را بالای کارت دارد و
 * پلنِ پیشنهادی گرادیان و قابِ روشن می‌گیرد؛ سوییچِ ماهانه/سالانه، فهرستِ «دارد/ندارد» و ردیفِ
 * سازمانی با دکمهٔ تماس با فروش. همیشه تیره است.
 */
export default function PricingDarkBlock() {
  const [billing, setBilling] = React.useState("year")

  return (
    <ControlSizeProvider size="xl" asChild>
      <main className="w-full bg-[var(--dig-graphite-950)] px-4 py-24 text-[var(--dig-white)] [--border:var(--dig-graphite-800)] [--muted-foreground:var(--dig-neutral-400)] sm:px-6">
        <div className="mx-auto flex w-full max-w-6xl flex-col gap-12">
          <header className="flex flex-col items-center gap-5 text-center">
            <h1 className="max-w-2xl text-4xl leading-tight font-black text-balance sm:text-6xl sm:leading-tight">قیمتی که با شما بزرگ می‌شود</h1>
            <p className="max-w-md text-muted-foreground">رایگان شروع کنید؛ هر وقت تیمتان بزرگ شد، پلن را عوض کنید.</p>
            <ToggleGroup
              type="single"
              variant="segmented"
              value={billing}
              onValueChange={(value) => value && setBilling(value as string)}
              aria-label="دورهٔ پرداخت"
              className="[--background:var(--dig-graphite-700)] [--foreground:var(--dig-white)] [--muted:var(--dig-graphite-900)]"
            >
              <ToggleGroupItem value="month">ماهانه</ToggleGroupItem>
              <ToggleGroupItem value="year">سالانه، ۲ ماه رایگان</ToggleGroupItem>
            </ToggleGroup>
          </header>

          <ul className="grid grid-cols-1 gap-4 md:grid-cols-3">
            {PLANS.map((plan, index) => {
              const price = billing === "year" ? Math.round((plan.month * 10) / 12) : plan.month
              const featured = "featured" in plan && plan.featured
              return (
                <Reveal asChild key={plan.name} delay={index * 100}>
                  <li className={cn("flex flex-col overflow-hidden rounded-xl border bg-[var(--dig-graphite-900)]", featured ? "border-[var(--dig-violet-400)] shadow-[0_0_60px_-20px_var(--dig-violet-500)]" : "border-[var(--dig-graphite-800)]")}>
                    <span aria-hidden className={cn("h-1.5", plan.band)} />
                    <div className="flex flex-1 flex-col gap-6 p-6">
                      <div className="flex flex-col gap-1">
                        <span className={cn("flex items-center justify-between font-bold", plan.accent)}>
                          {plan.name}
                          {featured && <span className="rounded-full bg-[var(--dig-violet-600)] px-2.5 py-0.5 text-xs text-[var(--dig-white)]">پیشنهادِ ما</span>}
                        </span>
                        <span className="text-sm text-muted-foreground">{plan.text}</span>
                      </div>
                      <span className="flex items-baseline gap-1.5">
                        <span className="text-4xl font-black tabular-nums">{price === 0 ? "رایگان" : price.toLocaleString("fa-IR")}</span>
                        {price > 0 && <span className="text-sm text-muted-foreground">هزار تومان / ماه</span>}
                      </span>
                      <Button
                        fullWidth
                        variant={featured ? "default" : "outline"}
                        className={cn(featured ? "[--primary-foreground:var(--dig-graphite-950)] [--primary:var(--dig-white)]" : "border-[var(--dig-graphite-700)] bg-transparent text-[var(--dig-white)] hover:bg-[var(--dig-graphite-800)]")}
                      >
                        {plan.month === 0 ? "شروعِ رایگان" : "انتخابِ پلن"}
                      </Button>
                      <ul className="flex flex-col gap-3 border-t border-border pt-5 text-sm">
                        {plan.features.map(([label, included]) => (
                          <li key={label} className={cn("flex items-center gap-2.5", !included && "text-[var(--dig-neutral-400)]")}>
                            {included ? <CheckIcon aria-label="دارد" className={cn("size-4", plan.accent)} /> : <MinusIcon aria-label="ندارد" className="size-4" />}
                            {label}
                          </li>
                        ))}
                      </ul>
                    </div>
                  </li>
                </Reveal>
              )
            })}
          </ul>

          <div className="flex flex-col items-start justify-between gap-4 rounded-xl border border-[var(--dig-graphite-800)] bg-[linear-gradient(90deg,var(--dig-graphite-900),var(--dig-graphite-950))] p-6 sm:flex-row sm:items-center">
            <div className="flex flex-col gap-1">
              <span className="text-lg font-bold">سازمانی</span>
              <span className="text-sm text-muted-foreground">قراردادِ اختصاصی، سرورِ جدا، پشتیبانیِ ۲۴ ساعته و مدیرِ حساب.</span>
            </div>
            <Button variant="outline" className="shrink-0 border-[var(--dig-graphite-700)] bg-transparent text-[var(--dig-white)] hover:bg-[var(--dig-graphite-800)]">
              تماس با فروش
              <ArrowUpIcon aria-hidden className="-rotate-45" />
            </Button>
          </div>
        </div>
      </main>
    </ControlSizeProvider>
  )
}