تنظیمات با ستونِ بخشها
پیشنمایش تمامصفحهتنظیمات با فهرستِ بخشها در کنار و محتوای بخش در ستونِ اصلی؛ ردیفهای تیتر و توضیح کنارِ کنترل (عکس، نام، ظاهر با سگمنت، سوییچ) و ذخیره در پایان.
۱. نصب کامپوننتها
این بلاک از ۹ آیتم دیگ استفاده میکند: avatarbuttoncontrol-sizeiconslabelswitchtext-fieldtoasttoggle-group
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/avatar.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/label.json https://docs.digdesign.ir/r/switch.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/toast.json https://docs.digdesign.ir/r/toggle-group.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/avatar.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/label.json https://docs.digdesign.ir/r/switch.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/toast.json https://docs.digdesign.ir/r/toggle-group.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/avatar.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/label.json https://docs.digdesign.ir/r/switch.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/toast.json https://docs.digdesign.ir/r/toggle-group.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/avatar.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/label.json https://docs.digdesign.ir/r/switch.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/toast.json https://docs.digdesign.ir/r/toggle-group.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
settings-sidebar.tsx
"use client"
import * as React from "react"
import { BellIcon, CreditCardIcon, GlobeIcon, ShieldCheckIcon, UserIcon } from "@/components/icons"
import { Avatar } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { TextField } from "@/components/ui/text-field"
import { toast } from "@/components/ui/toast"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { stockImages } from "@/lib/stock-images"
const SECTIONS = [
{ value: "account", label: "حساب", icon: <UserIcon /> },
{ value: "notifications", label: "اعلانها", icon: <BellIcon /> },
{ value: "security", label: "امنیت", icon: <ShieldCheckIcon /> },
{ value: "billing", label: "پرداخت", icon: <CreditCardIcon /> },
{ value: "language", label: "زبان و منطقه", icon: <GlobeIcon /> },
]
/**
* تنظیمات با ستونِ بخشها: فهرستِ بخشها در کنار (فعال روی کارتِ سفید با سایه، روی سطحِ
* muted) و محتوای همان بخش در ستونِ اصلی؛ هر بخش ردیفهای تیتر/توضیح در یک سو و کنترل
* در سوی دیگر دارد و «ذخیره» در پایانِ همان بخش.
*/
export default function SettingsSidebarBlock() {
const [section, setSection] = React.useState("account")
const [theme, setTheme] = React.useState("system")
const [weekly, setWeekly] = React.useState(true)
return (
<ControlSizeProvider size="xl" asChild>
<main className="mx-auto flex w-full max-w-5xl flex-col gap-8 p-4 sm:p-6">
<h1 className="text-2xl font-bold">تنظیمات</h1>
<div className="grid grid-cols-1 items-start gap-8 md:grid-cols-[15rem_minmax(0,1fr)]">
<nav aria-label="بخشهای تنظیمات" className="flex gap-1 overflow-x-auto rounded-xl bg-muted p-1.5 md:flex-col">
{SECTIONS.map((item) => (
<Button
key={item.value}
variant="ghost"
aria-current={item.value === section ? "page" : undefined}
onClick={() => setSection(item.value)}
className={`shrink-0 justify-start gap-3 font-normal ${item.value === section ? "bg-card font-semibold shadow-control hover:bg-card" : "hover:bg-card"}`}
>
<span aria-hidden className="text-muted-foreground [&>svg]:size-5">
{item.icon}
</span>
{item.label}
</Button>
))}
</nav>
<section aria-label={SECTIONS.find((item) => item.value === section)?.label} className="flex flex-col divide-y divide-border rounded-xl border border-border bg-card">
<div className="flex flex-wrap items-center gap-4 p-6">
<Avatar size="lg" alt="" src={stockImages.personWoman1.src} className="size-16" />
<div className="flex flex-1 flex-col">
<span className="font-semibold">عکسِ پروفایل</span>
<span className="text-sm text-muted-foreground">مربعی، حداقل ۴۰۰ پیکسل</span>
</div>
<Button variant="outline">تغییر</Button>
</div>
<div className="grid grid-cols-1 gap-4 p-6 sm:grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)] sm:items-start">
<div className="flex flex-col gap-1">
<span className="font-semibold">نام و ایمیل</span>
<span className="text-sm text-muted-foreground">در فاکتورها و پیامها دیده میشود.</span>
</div>
<div className="flex flex-col gap-4">
<TextField label="نام" defaultValue="مهسا کریمی" />
<TextField label="ایمیل" type="email" dir="ltr" defaultValue="mahsa@avand.example" />
</div>
</div>
<div className="grid grid-cols-1 gap-4 p-6 sm:grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)] sm:items-center">
<div className="flex flex-col gap-1">
<span id="ss-theme" className="font-semibold">
ظاهر
</span>
<span className="text-sm text-muted-foreground">روشن، تاریک یا مثلِ دستگاه.</span>
</div>
<ToggleGroup type="single" variant="segmented" value={theme} onValueChange={(value) => value && setTheme(value as string)} aria-labelledby="ss-theme" className="w-full">
<ToggleGroupItem value="light" className="flex-1">
روشن
</ToggleGroupItem>
<ToggleGroupItem value="dark" className="flex-1">
تاریک
</ToggleGroupItem>
<ToggleGroupItem value="system" className="flex-1">
دستگاه
</ToggleGroupItem>
</ToggleGroup>
</div>
<div className="flex items-center justify-between gap-4 p-6">
<div className="flex flex-col gap-1">
<Label htmlFor="ss-weekly" className="font-semibold">
خلاصهٔ هفتگی
</Label>
<span className="text-sm text-muted-foreground">هر شنبه گزارشِ کوتاهِ هفتهٔ قبل.</span>
</div>
<Switch id="ss-weekly" checked={weekly} onCheckedChange={setWeekly} />
</div>
<div className="flex justify-end gap-3 p-6">
<Button variant="outline">انصراف</Button>
<Button onClick={() => toast.success("تنظیمات ذخیره شد.")}>ذخیره</Button>
</div>
</section>
</div>
</main>
</ControlSizeProvider>
)
}