خانهٔ کیف پول (اپ)
پیشنمایش تمامصفحهخانهٔ اپِ بانکی: نوارِ بالا با عکس و اعلان، کارتِ تیرهٔ موجودی با نمایش/پنهان، چهار اقدامِ سریع، تراکنشهای اخیر با ردیفهای لمسی و نوارِ تبِ پایین.
۱. نصب کامپوننتها
این بلاک از ۸ آیتم دیگ استفاده میکند: app-baravatarbadgebottom-navigationbuttoncontrol-sizeiconspersian
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/app-bar.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/bottom-navigation.json 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.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/app-bar.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/bottom-navigation.json 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.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/app-bar.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/bottom-navigation.json 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.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/app-bar.json https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/bottom-navigation.json 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۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
mobile-wallet.tsx
"use client"
import * as React from "react"
import { ArrowUpIcon, BarChartIcon, BellIcon, CreditCardIcon, DashboardIcon, EyeIcon, EyeOffIcon, PhoneIcon, PlusIcon, ReceiptIcon, UserIcon, WalletIcon } from "@/components/icons"
import { AppBar, AppBarActions, AppBarLeading, AppBarTitle } from "@/components/ui/app-bar"
import { Avatar } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { BottomNavigation, BottomNavigationItem } from "@/components/ui/bottom-navigation"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { formatCurrency, toFaDigits } from "@/lib/persian"
import { stockImages } from "@/lib/stock-images"
const ACTIONS = [
{ label: "انتقال", icon: <ArrowUpIcon className="rotate-45" /> },
{ label: "افزایش", icon: <PlusIcon /> },
{ label: "قبض", icon: <ReceiptIcon /> },
{ label: "شارژ", icon: <PhoneIcon /> },
]
const TRANSACTIONS = [
{ title: "کافه رست", note: "امروز، ۱۰:۲۴", amount: -185_000 },
{ title: "واریزِ حقوق", note: "دیروز", amount: 32_000_000 },
{ title: "شارژِ همراه اول", note: "۱۲ مهر", amount: -50_000 },
{ title: "انتقال به سارا محمدی", note: "۱۱ مهر", amount: -1_200_000 },
]
/**
* خانهٔ کیف پول (پوستهٔ اپ): نوارِ بالا با عکسِ کاربر و اعلان، کارتِ موجودی تیره با
* نمایش/پنهان، چهار اقدامِ سریع، تراکنشهای اخیر با ردیفهای کاملاً لمسی، و نوارِ تبِ پایین.
*/
export default function MobileWalletBlock() {
const [hidden, setHidden] = React.useState(false)
const [tab, setTab] = React.useState("home")
return (
<ControlSizeProvider size="xl" asChild>
<div className="mx-auto flex min-h-svh w-full max-w-md flex-col bg-background">
<AppBar sticky>
<AppBarLeading>
<Avatar alt="مهسا کریمی" src={stockImages.personWoman1.src} />
</AppBarLeading>
<AppBarTitle className="flex flex-col items-start text-start">
<span className="text-xs font-normal text-muted-foreground">سلام،</span>
مهسا
</AppBarTitle>
<AppBarActions>
<Button variant="ghost" size="icon" aria-label="اعلانها، ۳ تازه" className="relative">
<BellIcon />
<span aria-hidden className="absolute end-2 top-2 size-2 rounded-full bg-destructive" />
</Button>
</AppBarActions>
</AppBar>
<main className="flex flex-1 flex-col gap-6 p-4">
<section aria-label="موجودی" className="flex flex-col gap-4 rounded-xl bg-inverse p-5 text-[var(--dig-white)]">
<div className="flex items-center justify-between">
<span className="text-sm text-[var(--dig-neutral-400)]">موجودی کیف پول</span>
<Button variant="ghost" size="icon" aria-label={hidden ? "نمایشِ موجودی" : "پنهانکردنِ موجودی"} aria-pressed={hidden} onClick={() => setHidden((value) => !value)} className="text-[var(--dig-white)] hover:bg-inverse-raised">
{hidden ? <EyeIcon /> : <EyeOffIcon />}
</Button>
</div>
<span className="text-3xl font-black tabular-nums">{hidden ? "••••••" : formatCurrency(48_250_000)}</span>
<span className="flex items-center gap-2 text-sm text-[var(--dig-neutral-400)]">
<CreditCardIcon aria-hidden className="size-4" />
<bdi dir="ltr">{toFaDigits("6037 •••• •••• 5678")}</bdi>
</span>
</section>
<nav aria-label="اقدامهای سریع" className="grid grid-cols-4 gap-3">
{ACTIONS.map((action) => (
<Button key={action.label} variant="ghost" className="h-auto flex-col gap-2 rounded-xl bg-subtle py-4 font-normal hover:bg-muted">
<span aria-hidden className="flex size-10 items-center justify-center rounded-full bg-card text-brand-secondary [&>svg]:size-5">
{action.icon}
</span>
<span className="text-sm">{action.label}</span>
</Button>
))}
</nav>
<section aria-labelledby="wallet-recent" className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<h2 id="wallet-recent" className="font-bold">
تراکنشهای اخیر
</h2>
<Button variant="ghost">همه</Button>
</div>
<ul className="flex flex-col divide-y divide-border">
{TRANSACTIONS.map((item) => (
<li key={item.title + item.note}>
<a href="#" className="flex min-h-16 items-center gap-3 py-3">
<span aria-hidden className="flex size-11 shrink-0 items-center justify-center rounded-full bg-subtle [&>svg]:size-5">
{item.amount > 0 ? <WalletIcon className="text-success" /> : <ReceiptIcon className="text-muted-foreground" />}
</span>
<span className="flex flex-1 flex-col">
<span className="font-medium">{item.title}</span>
<span className="text-sm text-muted-foreground">{item.note}</span>
</span>
<span className={`font-bold tabular-nums ${item.amount > 0 ? "text-success" : ""}`}>
<bdi dir="ltr">{item.amount > 0 ? "+" : "−"}{toFaDigits(Math.abs(item.amount).toLocaleString("en-US"))}</bdi>
</span>
</a>
</li>
))}
</ul>
</section>
</main>
<BottomNavigation value={tab} onValueChange={setTab} indicator="pill" fixed={false} className="sticky bottom-0 pb-[env(safe-area-inset-bottom)]">
<BottomNavigationItem value="home" icon={<DashboardIcon />} label="خانه" />
<BottomNavigationItem value="cards" icon={<CreditCardIcon />} label="کارتها" />
<BottomNavigationItem value="reports" icon={<BarChartIcon />} label="گزارش" />
<BottomNavigationItem value="profile" icon={<UserIcon />} label="حساب" badge={<Badge color="destructive">{toFaDigits(1)}</Badge>} />
</BottomNavigation>
</div>
</ControlSizeProvider>
)
}