مقالهٔ راهنما
پیشنمایش تمامصفحهمستندات: فهرستِ راهنماها با صفحهٔ فعال، مسیرِ صفحه، گامهای شمارهدار، فهرستِ مطالبِ چسبان و «این راهنما مفید بود؟».
۱. نصب کامپوننتها
این بلاک از ۴ آیتم دیگ استفاده میکند: breadcrumbbuttoncontrol-sizeicons
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/breadcrumb.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/breadcrumb.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/breadcrumb.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/breadcrumb.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
article-docs.tsx
"use client"
import * as React from "react"
import { ChevronDownIcon, ThumbsDownIcon, ThumbsUpIcon } from "@/components/icons"
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
const TOC = [
{ id: "need", title: "پیش از شروع" },
{ id: "steps", title: "مراحلِ ساختِ فاکتور" },
{ id: "send", title: "ارسال برای مشتری" },
{ id: "faq", title: "خطاهای رایج" },
]
const NAV = ["شروعِ کار", "ساختِ فاکتور", "ارسالِ پیامکی", "گزارشها", "تنظیماتِ مالیات"]
/**
* مقالهٔ راهنما (مستندات): فهرستِ راهنماها در ستونِ راست با صفحهٔ فعال، متن با مسیرِ
* صفحه و گامهای شمارهدار، فهرستِ مطالب در ستونِ چپ، و «این راهنما مفید بود؟» در پایان.
*/
export default function ArticleDocsBlock() {
const [vote, setVote] = React.useState<"up" | "down" | null>(null)
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-[13rem_minmax(0,1fr)_12rem]">
<nav aria-label="راهنماها" className="hidden flex-col gap-1 lg:flex lg:sticky lg:top-6">
{NAV.map((item) => (
<a
key={item}
href="#"
aria-current={item === "ساختِ فاکتور" ? "page" : undefined}
className={`rounded-lg px-3 py-2.5 text-sm ${item === "ساختِ فاکتور" ? "bg-primary-subtle font-semibold" : "text-muted-foreground hover:bg-subtle hover:text-foreground"}`}
>
{item}
</a>
))}
</nav>
<article className="flex flex-col gap-8">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#">راهنما</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>ساختِ فاکتور</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
{/* در موبایل ستونهای کناری پنهاناند؛ راهنماهای دیگر و فهرستِ مطالب در یک بازشو. */}
<details className="group rounded-xl border border-border bg-card lg:hidden">
<summary className="flex min-h-12 cursor-pointer list-none items-center justify-between gap-3 px-4 text-sm font-medium [&::-webkit-details-marker]:hidden">
فهرستِ راهنما و مطالب
<ChevronDownIcon aria-hidden className="size-4 text-muted-foreground transition-transform group-open:rotate-180" />
</summary>
<div className="grid grid-cols-1 gap-4 border-t border-border p-4 sm:grid-cols-2">
<nav aria-label="راهنماها (موبایل)" className="flex flex-col gap-1">
<span className="px-3 pb-1 text-xs font-medium text-muted-foreground">راهنماها</span>
{NAV.map((item) => (
<a key={item} href="#" aria-current={item === "ساختِ فاکتور" ? "page" : undefined} className={`flex min-h-11 items-center rounded-lg px-3 text-sm ${item === "ساختِ فاکتور" ? "bg-primary-subtle font-semibold" : "text-muted-foreground"}`}>
{item}
</a>
))}
</nav>
<nav aria-label="در این صفحه (موبایل)" className="flex flex-col gap-1">
<span className="px-3 pb-1 text-xs font-medium text-muted-foreground">در این صفحه</span>
{TOC.map((item) => (
<a key={item.id} href={`#${item.id}`} className="flex min-h-11 items-center rounded-lg px-3 text-sm text-muted-foreground">
{item.title}
</a>
))}
</nav>
</div>
</details>
<header className="flex flex-col gap-3">
<h1 className="text-3xl font-bold">ساختِ اولین فاکتور</h1>
<p className="text-lg leading-8 text-muted-foreground">در کمتر از دو دقیقه فاکتورِ رسمی بساز و برای مشتری بفرست.</p>
</header>
<section id="need" className="flex flex-col gap-3 scroll-mt-6">
<h2 className="text-xl font-bold">پیش از شروع</h2>
<p className="leading-8 text-muted-foreground">اطلاعاتِ شرکت و لوگو را در «تنظیمات ← کسبوکار» کامل کن تا روی فاکتور بیاید.</p>
</section>
<section id="steps" className="flex flex-col gap-4 scroll-mt-6">
<h2 className="text-xl font-bold">مراحلِ ساختِ فاکتور</h2>
<ol className="flex flex-col gap-4">
{["از منوی «فاکتورها» دکمهٔ «فاکتورِ تازه» را بزن.", "مشتری را انتخاب کن یا تازه بساز.", "اقلام، تعداد و تخفیف را وارد کن؛ مالیات خودش حساب میشود.", "«ذخیره» را بزن؛ شماره خودکار میگیرد."].map((step, index) => (
<li key={step} className="flex gap-4">
<span aria-hidden className="flex size-8 shrink-0 items-center justify-center rounded-full bg-subtle text-sm font-bold">
{"۱۲۳۴"[index]}
</span>
<span className="pt-1 leading-7">{step}</span>
</li>
))}
</ol>
</section>
<section id="send" className="flex flex-col gap-3 scroll-mt-6">
<h2 className="text-xl font-bold">ارسال برای مشتری</h2>
<p className="leading-8 text-muted-foreground">در صفحهٔ فاکتور «ارسال» را بزن؛ مشتری پیامکی با لینکِ مشاهده و پرداخت میگیرد.</p>
</section>
<section id="faq" className="flex flex-col gap-3 rounded-xl bg-subtle p-5 scroll-mt-6">
<h2 className="font-bold">خطاهای رایج</h2>
<p className="text-sm leading-7 text-muted-foreground">«شمارهٔ مشتری نامعتبر است»: شماره باید با ۰۹ شروع شود و ۱۱ رقم باشد.</p>
</section>
<div className="flex flex-wrap items-center gap-4 border-t border-border pt-8" aria-live="polite">
{vote ? (
<span className="text-sm">ممنون از بازخوردت!</span>
) : (
<>
<span className="text-sm font-medium">این راهنما مفید بود؟</span>
<Button variant="outline" onClick={() => setVote("up")}>
<ThumbsUpIcon />
بله
</Button>
<Button variant="outline" onClick={() => setVote("down")}>
<ThumbsDownIcon />
نه
</Button>
</>
)}
</div>
</article>
<nav aria-label="در این صفحه" className="hidden flex-col gap-2 text-sm lg:flex lg:sticky lg:top-6">
<span className="font-semibold">در این صفحه</span>
{TOC.map((item) => (
<a key={item.id} href={`#${item.id}`} className="text-muted-foreground hover:text-foreground">
{item.title}
</a>
))}
</nav>
</main>
</ControlSizeProvider>
)
}