منوی کناری اپ
پیشنمایش تمامصفحهکشوی منو از لبهٔ شروع با پروفایل، موجودی کیف پول، پیوندها با شمارنده، حالت شب و خروج.
۱. نصب کامپوننتها
این بلاک از ۱۰ آیتم دیگ استفاده میکند: app-baravatarbadgebuttoncontrol-sizeiconspersianseparatorsheetswitch
پکیجمنیجر پیشفرض 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/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/separator.json https://docs.digdesign.ir/r/sheet.json https://docs.digdesign.ir/r/switch.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/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/separator.json https://docs.digdesign.ir/r/sheet.json https://docs.digdesign.ir/r/switch.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/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/separator.json https://docs.digdesign.ir/r/sheet.json https://docs.digdesign.ir/r/switch.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/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/separator.json https://docs.digdesign.ir/r/sheet.json https://docs.digdesign.ir/r/switch.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
mobile-menu.tsx
"use client"
import * as React from "react"
import {
BellIcon,
CreditCardIcon,
GuideIcon,
HeartIcon,
LogoutIcon,
MenuIcon,
MoonIcon,
ReceiptIcon,
SettingsIcon,
ShopIcon,
TicketIcon,
WalletIcon,
} from "@/components/icons"
import { AppBar, AppBarActions, AppBarLeading, AppBarTitle } from "@/components/ui/app-bar"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Avatar } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Separator } from "@/components/ui/separator"
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet"
import { Switch } from "@/components/ui/switch"
import { formatCurrency, toFaDigits } from "@/lib/persian"
import { stockImages } from "@/lib/stock-images"
const MAIN = [
{ title: "خانه", icon: <ShopIcon />, active: true },
{ title: "سفارشهای من", icon: <ReceiptIcon />, badge: toFaDigits(2) },
{ title: "علاقهمندیها", icon: <HeartIcon /> },
{ title: "کیف پول", icon: <WalletIcon /> },
{ title: "کارتهای بانکی", icon: <CreditCardIcon /> },
]
const SUPPORT = [
{ title: "اعلانها", icon: <BellIcon />, badge: toFaDigits(5) },
{ title: "پشتیبانی", icon: <TicketIcon /> },
{ title: "راهنما", icon: <GuideIcon /> },
{ title: "تنظیمات", icon: <SettingsIcon /> },
]
function MenuLink({ item }: { item: { title: string; icon: React.ReactNode; active?: boolean; badge?: string } }) {
return (
<a
href="#"
aria-current={item.active ? "page" : undefined}
className={
item.active
? "flex h-12 items-center gap-3 rounded-lg bg-primary-subtle px-3 font-semibold text-foreground [&_svg]:size-5 [&_svg]:text-brand-secondary"
: "flex h-12 items-center gap-3 rounded-lg px-3 text-foreground transition-colors hover:bg-subtle [&_svg]:size-5 [&_svg]:text-muted-foreground"
}
>
{item.icon}
<span className="flex-1">{item.title}</span>
{item.badge && (
<Badge color="destructive">
{item.badge}
</Badge>
)}
</a>
)
}
/**
* منوی کناری اپ: در موبایل از لبهٔ شروع (راست در RTL) باز میشود. برای
* پنلِ وب از Sidebar استفاده کنید که در موبایل خودش به همین کشو تبدیل میشود.
*/
export default function MobileMenuBlock() {
const [open, setOpen] = React.useState(true)
const [dark, setDark] = React.useState(false)
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>
<Button variant="ghost" size="icon" aria-label="باز کردن منو" onClick={() => setOpen(true)}>
<MenuIcon />
</Button>
</AppBarLeading>
<AppBarTitle>فروشگاه دیگ</AppBarTitle>
<AppBarActions>
<Avatar alt="آرمیتا رستگار" size="sm" src={stockImages.personWoman1.src} />
</AppBarActions>
</AppBar>
<main className="flex flex-1 items-center justify-center p-6 text-center text-sm text-muted-foreground">
منو را با دکمهٔ بالا باز کنید.
</main>
<Sheet open={open} onOpenChange={setOpen}>
<ControlSizeProvider size="xl" asChild>
<SheetContent side="start" className="flex w-[85%] max-w-xs flex-col gap-0 p-0">
<SheetHeader className="gap-5 border-b border-border p-4 pt-6">
<SheetTitle className="sr-only">منوی اصلی</SheetTitle>
<div className="flex items-center gap-3">
<Avatar alt="آرمیتا رستگار" size="lg" src={stockImages.personWoman1.src} />
<div className="flex min-w-0 flex-col">
<span className="truncate font-semibold">آرمیتا رستگار</span>
<bdi dir="ltr" className="text-sm text-muted-foreground">
{toFaDigits("0912 123 4567")}
</bdi>
</div>
</div>
<div className="flex items-center justify-between gap-3 rounded-xl bg-inverse p-4 text-[var(--dig-white)] [--muted-foreground:var(--dig-neutral-400)]">
<span className="flex flex-col gap-0.5">
<span className="text-xs text-muted-foreground">موجودی کیف پول</span>
<span className="text-lg font-black tabular-nums">{formatCurrency(1_345_000)}</span>
</span>
<Button variant="ghost" className="text-[var(--dig-white)] hover:bg-inverse-raised">
افزایش
</Button>
</div>
</SheetHeader>
<nav aria-label="منوی اصلی" className="flex flex-1 flex-col gap-1 overflow-y-auto p-4">
{MAIN.map((item) => (
<MenuLink key={item.title} item={item} />
))}
<Separator className="my-2" />
{SUPPORT.map((item) => (
<MenuLink key={item.title} item={item} />
))}
<div className="flex h-12 items-center gap-3 px-3 [&_svg]:size-5 [&_svg]:text-muted-foreground">
<MoonIcon />
<label htmlFor="dark-mode" className="flex-1">
حالت شب
</label>
<Switch id="dark-mode" checked={dark} onCheckedChange={setDark} />
</div>
</nav>
<div className="border-t border-border p-4">
<Button variant="ghost" color="destructive" fullWidth className="justify-start">
<LogoutIcon />
خروج از حساب
</Button>
</div>
</SheetContent>
</ControlSizeProvider>
</Sheet>
</div>
</ControlSizeProvider>
)
}