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

لندینگ اپ موبایل

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

معرفیِ اپ: هیروی تیره با پترنِ نقطه‌ای و گوشیِ واقعی‌نما، دکمه‌های دانلود و کاربرانِ واقعی، ویژگی‌ها با آیکونِ رنگی، سه قدمِ شروع، آمارِ شمارنده با نظرِ کاربر، پرسش‌ها و دعوتِ پایانی.

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

این بلاک از ۱۱ آیتم دیگ استفاده می‌کند: accordionavatarbackground-patternbadgebuttoncontrol-sizecount-upfootericonspersianreveal

پکیج‌منیجر پیش‌فرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیج‌منیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/background-pattern.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/count-up.json https://docs.digdesign.ir/r/footer.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.json
pnpm dlx digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/background-pattern.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/count-up.json https://docs.digdesign.ir/r/footer.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.json
yarn dlx digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/background-pattern.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/count-up.json https://docs.digdesign.ir/r/footer.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.json
bunx --bun digdesign@latest add https://docs.digdesign.ir/r/accordion.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/background-pattern.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/count-up.json https://docs.digdesign.ir/r/footer.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 بگذارید و متن‌ها، داده و هندلرها را با محصول خودتان عوض کنید.

app-landing.tsx
"use client"

import * as React from "react"

import {
  ArrowUpIcon,
  BellIcon,
  CheckIcon,
  CreditCardIcon,
  DownloadIcon,
  ShieldCheckIcon,
  StarIcon,
  WalletIcon,
} from "@/components/icons"
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Avatar, AvatarGroup } from "@/components/ui/avatar"
import { DotPattern } from "@/components/ui/background-pattern"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { CountUp } from "@/components/ui/count-up"
import {
  Footer,
  FooterBottom,
  FooterBrand,
  FooterColumn,
  FooterColumns,
  FooterColumnTitle,
  FooterContent,
  FooterLink,
  FooterLinkList,
} from "@/components/ui/footer"
import { Reveal } from "@/components/ui/reveal"
import { formatCurrency, toFaDigits } from "@/lib/persian"
import { stockImages } from "@/lib/stock-images"

const FEATURES = [
  { icon: <WalletIcon />, tone: "violet", title: "کیف پولِ یکپارچه", text: "موجودی همهٔ کارت‌ها در یک صفحه، با دسته‌بندی خودکارِ هزینه‌ها." },
  { icon: <CreditCardIcon />, tone: "blue", title: "کارت‌به‌کارتِ بی‌کارمزد", text: "تا ۳ انتقال در روز بدونِ کارمزد، به همهٔ بانک‌ها." },
  { icon: <BellIcon />, tone: "amber", title: "یادآورِ قسط و قبض", text: "یک روز قبل از سررسید خبرت می‌کنیم؛ دیگر جریمه نمی‌دهی." },
  { icon: <ShieldCheckIcon />, tone: "green", title: "امنیتِ بانکی", text: "ورودِ دومرحله‌ای، اثرِ انگشت و قفلِ آنی کارت از داخلِ اپ." },
]

const STEPS = [
  { title: "اپ را نصب کن", text: "از کافه‌بازار، مایکت یا مستقیم." },
  { title: "با کد ملی ثبت‌نام کن", text: "احرازِ هویت کمتر از دو دقیقه." },
  { title: "کارت‌هایت را وصل کن", text: "همهٔ حساب‌ها در یک نگاه." },
]

const FAQ = [
  { q: "اپ رایگان است؟", a: "بله؛ نصب و استفاده رایگان است و فقط برای بعضی خدماتِ ویژه کارمزد می‌گیریم." },
  { q: "اطلاعاتِ کارتم امن است؟", a: "رمزها هرگز ذخیره نمی‌شوند و همهٔ ارتباط‌ها رمزنگاری‌شده‌اند." },
  { q: "روی آیفون هم نصب می‌شود؟", a: "بله؛ نسخهٔ وب‌اپ روی آیفون و نسخهٔ کامل روی اندروید." },
]

/** پیش‌نمایشِ گوشی با صفحهٔ اصلی اپ (تزئینی)؛ توکن‌های روشن را دوباره تعریف می‌کند چون داخلِ هیروی تیره است. */
function PhoneMock() {
  return (
    <div aria-hidden className="relative mx-auto w-64 rounded-[2.5rem] border-[10px] border-[var(--dig-graphite-950)] bg-[var(--dig-white)] text-[var(--dig-graphite-900)] shadow-overlay sm:w-72 [--border:var(--dig-neutral-200)] [--card:var(--dig-white)] [--foreground:var(--dig-graphite-900)] [--muted-foreground:var(--dig-neutral-500)] [--muted:var(--dig-neutral-100)]">
      <div className="mx-auto mt-2 h-5 w-24 rounded-full bg-inverse" />
      <div className="flex flex-col gap-4 p-4">
        <div className="flex items-center justify-between">
          <span className="text-sm font-semibold">سلام، سارا</span>
          <Avatar size="sm" alt="" src={stockImages.personWoman3.src} />
        </div>
        <div className="flex flex-col gap-1 rounded-xl bg-[var(--dig-violet-700)] p-4 text-[var(--dig-white)]">
          <span className="text-xs text-[var(--dig-violet-200)]">موجودی کل</span>
          <span className="text-xl font-bold tabular-nums">{formatCurrency(48_250_000)}</span>
          <span className="mt-2 flex items-center gap-1 text-xs text-[var(--dig-green-300)]">
            <ArrowUpIcon className="size-3" />
            ۱۲٪ نسبت به ماهِ قبل
          </span>
        </div>
        <div className="grid grid-cols-3 gap-2 text-center text-xs">
          {["انتقال", "قبض", "شارژ"].map((label) => (
            <span key={label} className="flex flex-col items-center gap-1.5 rounded-lg bg-muted py-3">
              <span className="size-6 rounded-full bg-[color-mix(in_oklab,var(--dig-violet-500)_18%,var(--card))]" />
              {label}
            </span>
          ))}
        </div>
        <div className="flex flex-col gap-2">
          {[
            { title: "کافه رست", amount: -185_000 },
            { title: "واریزِ حقوق", amount: 32_000_000 },
            { title: "اسنپ", amount: -96_000 },
          ].map((row) => (
            <span key={row.title} className="flex items-center justify-between rounded-lg border border-border px-3 py-2 text-xs">
              <span className="font-medium">{row.title}</span>
              <span className={row.amount > 0 ? "font-semibold text-success tabular-nums" : "font-semibold tabular-nums"}>
                {row.amount > 0 ? "+" : "−"}
                {formatCurrency(Math.abs(row.amount))}
              </span>
            </span>
          ))}
        </div>
      </div>
    </div>
  )
}

/**
 * لندینگِ اپِ موبایل: هیروی تیره با گوشی واقعی‌نما و دکمه‌های دانلود، ویژگی‌ها با
 * آیکونِ رنگی، سه قدمِ شروع، آمارِ شمارنده، نظرِ کاربران، پرسش‌ها و دعوتِ پایانی.
 */
export default function AppLandingBlock() {
  return (
    <ControlSizeProvider size="xl" asChild>
      <div className="flex min-h-svh flex-col bg-background">
        {/* قهرمانِ تیره با پترنِ نقطه‌ای؛ متن در شروع و گوشی در پایان. */}
        <section className="relative overflow-hidden bg-inverse text-[var(--dig-white)] [--background:var(--inverse)] [--border:var(--inverse-border)] [--foreground:var(--dig-white)] [--muted-foreground:var(--dig-neutral-400)] [--primary-foreground:var(--dig-graphite-950)] [--primary:var(--dig-white)]">
          <DotPattern size={22} />
          <span aria-hidden className="absolute -end-32 top-24 size-[28rem] rounded-full bg-[var(--dig-violet-800)] blur-3xl" />
          <header className="relative mx-auto flex h-16 w-full max-w-6xl items-center justify-between px-4 sm:px-6">
            <span className="flex items-center gap-2 text-lg font-black">
              <span aria-hidden className="size-7 rounded-lg bg-[var(--dig-violet-500)]" />
              سکه
            </span>
            <nav aria-label="ناوبری اصلی" className="hidden gap-6 text-sm text-muted-foreground md:flex">
              {["امکانات", "امنیت", "پرسش‌ها"].map((item) => (
                <a key={item} href="#" className="transition-colors hover:text-foreground">
                  {item}
                </a>
              ))}
            </nav>
          </header>
          <div className="relative mx-auto grid grid-cols-1 w-full max-w-6xl items-center gap-12 px-4 pt-12 pb-20 sm:px-6 lg:grid-cols-2 lg:pt-16 lg:pb-28">
            <div className="flex flex-col gap-6">
              <Badge variant="outline" className="self-start border-inverse-border bg-inverse-raised text-[var(--dig-white)]">
                <StarIcon className="size-3.5 fill-current text-[var(--dig-amber-400)]" />
                امتیازِ ۴٫۸ در کافه‌بازار
              </Badge>
              <h1 className="text-4xl leading-snug font-black sm:text-6xl sm:leading-snug">همهٔ پولت، در یک اپ.</h1>
              <p className="max-w-lg text-lg leading-8 text-muted-foreground">
                موجودی، انتقال، قبض و قسط؛ ساده، سریع و امن. بیش از نیم میلیون نفر هر روز با سکه حساب‌وکتاب می‌کنند.
              </p>
              <div className="mt-2 flex flex-wrap gap-3">
                <Button>
                  <DownloadIcon />
                  دانلود از کافه‌بازار
                </Button>
                <Button variant="outline" className="border-inverse-border bg-inverse-raised text-[var(--dig-white)] hover:bg-inverse-border hover:text-[var(--dig-white)]">
                  نسخهٔ آیفون
                </Button>
              </div>
              <div className="mt-2 flex items-center gap-3 text-sm text-muted-foreground">
                <AvatarGroup>
                  {[stockImages.personMan1, stockImages.personWoman1, stockImages.personMan2].map((photo) => (
                    <Avatar key={photo.src} size="sm" alt="" src={photo.src} className="ring-2 ring-inverse" />
                  ))}
                </AvatarGroup>
                بیش از ۵۰۰ هزار کاربرِ فعال
              </div>
            </div>
            <PhoneMock />
          </div>
        </section>

        <main className="flex flex-col">
          {/* ویژگی‌ها: چهار کارت با کاشی آیکونِ رنگی. */}
          <section aria-labelledby="app-features" className="mx-auto flex w-full max-w-6xl flex-col gap-12 px-4 py-24 sm:px-6">
            <div className="flex max-w-2xl flex-col gap-3">
              <h2 id="app-features" className="text-3xl font-black sm:text-4xl">
                چیزهایی که هر روز لازم داری
              </h2>
              <p className="text-lg leading-8 text-muted-foreground">بدونِ رفتن به شعبه و بدونِ اپ‌های جداجدا.</p>
            </div>
            <ul className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
              {FEATURES.map((feature, index) => (
                <Reveal asChild key={feature.title} delay={index * 100}>
                  <li className="flex flex-col gap-4 rounded-xl border border-border bg-card p-6 transition-[opacity,translate,box-shadow] hover:shadow-card">
                    <span
                      aria-hidden
                      className="flex size-11 items-center justify-center rounded-xl [&>svg]:size-5"
                      style={{ background: `color-mix(in oklab, var(--dig-${feature.tone}-500) 12%, var(--card))`, color: `var(--dig-${feature.tone}-600)` }}
                    >
                      {feature.icon}
                    </span>
                    <span className="font-bold">{feature.title}</span>
                    <span className="text-sm leading-7 text-muted-foreground">{feature.text}</span>
                  </li>
                </Reveal>
              ))}
            </ul>
          </section>

          {/* سه قدم با شماره‌های بزرگ و خطِ اتصال. */}
          <section aria-labelledby="app-steps" className="bg-muted py-24">
            <div className="mx-auto flex w-full max-w-6xl flex-col gap-12 px-4 sm:px-6">
              <div className="flex max-w-2xl flex-col gap-3">
                <h2 id="app-steps" className="text-3xl font-black sm:text-4xl">
                  در سه قدم شروع کن
                </h2>
                <p className="text-lg leading-8 text-muted-foreground">کمتر از پنج دقیقه از نصب تا اولین انتقال.</p>
              </div>
              <ol className="grid grid-cols-1 gap-8 md:grid-cols-3">
                {STEPS.map((step, index) => (
                  <Reveal asChild key={step.title} delay={index * 100}>
                    <li className="flex flex-col gap-3 border-t-2 border-[var(--dig-violet-500)] pt-6">
                      <span className="text-4xl font-black text-[var(--dig-violet-600)] tabular-nums">{toFaDigits(index + 1)}</span>
                      <span className="text-lg font-bold">{step.title}</span>
                      <span className="text-muted-foreground">{step.text}</span>
                    </li>
                  </Reveal>
                ))}
              </ol>
            </div>
          </section>

          {/* آمار با شمارنده و نظرِ یک کاربر کنارش. */}
          <section className="mx-auto grid grid-cols-1 w-full max-w-6xl gap-6 px-4 py-24 sm:px-6 lg:grid-cols-[1fr_1.2fr]">
            <dl className="grid grid-cols-2 gap-4">
              {[
                { value: 500, suffix: "+ هزار", label: "کاربرِ فعال" },
                { value: 4.8, decimals: 1, label: "امتیاز در استورها" },
                { value: 12, suffix: "+ میلیون", label: "تراکنشِ ماهانه" },
                { value: 99.9, decimals: 1, suffix: "٪", label: "دسترس‌پذیری" },
              ].map((stat) => (
                <div key={stat.label} className="flex flex-col gap-1 rounded-xl border border-border p-6">
                  <dt className="order-2 text-sm text-muted-foreground">{stat.label}</dt>
                  <dd className="text-3xl font-black">
                    <CountUp value={stat.value} decimals={stat.decimals ?? 0} suffix={stat.suffix} />
                  </dd>
                </div>
              ))}
            </dl>
            <figure className="flex flex-col justify-between gap-8 rounded-xl bg-[var(--dig-violet-800)] p-8 text-[var(--dig-white)] [--muted-foreground:var(--dig-violet-200)]">
              <span className="flex gap-0.5 text-[var(--dig-amber-400)]" role="img" aria-label="امتیاز ۵ از ۵">
                {[0, 1, 2, 3, 4].map((star) => (
                  <StarIcon key={star} className="size-5 fill-current" aria-hidden />
                ))}
              </span>
              <blockquote className="text-xl leading-9 font-bold">
                «اولین اپی که واقعاً می‌فهمم پولم کجا می‌رود. یادآورِ قسط هم چند بار نجاتم داده.»
              </blockquote>
              <figcaption className="flex items-center gap-3">
                <Avatar alt="لیلا احمدی" src={stockImages.personWoman2.src} />
                <span className="flex flex-col">
                  <span className="font-semibold">لیلا احمدی</span>
                  <span className="text-sm text-muted-foreground">کاربرِ سکه از ۱۴۰۲</span>
                </span>
              </figcaption>
            </figure>
          </section>

          <section aria-labelledby="app-faq" className="mx-auto grid grid-cols-1 w-full max-w-6xl gap-12 px-4 pb-24 sm:px-6 lg:grid-cols-[1fr_1.4fr]">
            <div className="flex flex-col gap-3">
              <h2 id="app-faq" className="text-3xl font-black sm:text-4xl">
                پرسش‌های رایج
              </h2>
              <p className="text-lg leading-8 text-muted-foreground">جوابت این‌جا نیست؟ داخلِ اپ با پشتیبانی گفت‌وگو کن.</p>
            </div>
            <Accordion type="single" collapsible variant="soft" indicator="plus" defaultValue={FAQ[0].q}>
              {FAQ.map((item) => (
                <AccordionItem key={item.q} value={item.q}>
                  <AccordionTrigger className="text-base font-semibold">{item.q}</AccordionTrigger>
                  <AccordionContent className="leading-8 text-muted-foreground">{item.a}</AccordionContent>
                </AccordionItem>
              ))}
            </Accordion>
          </section>

          {/* دعوتِ پایانی روی کارتِ بنفش. */}
          <section className="mx-auto w-full max-w-6xl px-4 pb-24 sm:px-6">
            <div className="flex flex-col items-start gap-6 rounded-xl bg-[var(--dig-violet-700)] p-8 text-[var(--dig-white)] sm:flex-row sm:items-center sm:justify-between sm:p-12 [--muted-foreground:var(--dig-violet-100)] [--primary-foreground:var(--dig-violet-800)] [--primary:var(--dig-white)]">
              <div className="flex flex-col gap-2">
                <h2 className="text-3xl font-black">همین امروز نصبش کن</h2>
                <p className="flex items-center gap-2 text-muted-foreground">
                  <CheckIcon className="size-4" aria-hidden />
                  رایگان، بدونِ مراجعهٔ حضوری
                </p>
              </div>
              <Button>
                <DownloadIcon />
                دانلود اپ
              </Button>
            </div>
          </section>
        </main>

        <Footer>
          <FooterContent>
            <FooterBrand>
              <span className="text-lg font-black">سکه</span>
              <p className="text-sm text-muted-foreground">اپِ مدیریتِ مالی شخصی.</p>
            </FooterBrand>
            <FooterColumns>
              <FooterColumn>
                <FooterColumnTitle>اپ</FooterColumnTitle>
                <FooterLinkList>
                  <FooterLink href="#">امکانات</FooterLink>
                  <FooterLink href="#">امنیت</FooterLink>
                </FooterLinkList>
              </FooterColumn>
              <FooterColumn>
                <FooterColumnTitle>پشتیبانی</FooterColumnTitle>
                <FooterLinkList>
                  <FooterLink href="#">پرسش‌ها</FooterLink>
                  <FooterLink href="#">تماس</FooterLink>
                </FooterLinkList>
              </FooterColumn>
            </FooterColumns>
          </FooterContent>
          <FooterBottom>
            <span>© {toFaDigits(1405)} سکه</span>
          </FooterBottom>
        </Footer>
      </div>
    </ControlSizeProvider>
  )
}