دیالوگ (Dialog)
کامپوننت نمایش پنجرههای مودال
معرفی
کامپوننت Dialog برای نمایش محتوا در یک پنجره مودال که روی صفحه اصلی قرار میگیرد استفاده میشود.
چه زمانی استفاده کنیم:
- برای عملیات کوتاه که نیاز به تمرکز کاربر دارند (ویرایش پروفایل، افزودن آیتم)
- برای فرمهای ساده (تا ۵ فیلد) که در context صفحه فعلی معنا دارند
- برای تأیید عملیات غیر مخرب
چه زمانی استفاده نکنیم:
- برای تأیید اعمال destructive — از
AlertDialogاستفاده کنید - برای محتوای بزرگ در موبایل — از
Drawerاستفاده کنید - برای منوهای کشویی ساده — از
DropdownMenuاستفاده کنید - برای فرمهای بلند (بیش از ۵ فیلد) — از
Sheetاستفاده کنید
استفاده
زمین بازی
با تغییر تنظیمات زیر، دیالوگ را به صورت زنده مشاهده کنید.
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Button } from '@partodata/ui'
<Dialog>
<DialogTrigger asChild>
<Button type="outline">باز کردن دیالوگ</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>عنوان دیالوگ</DialogTitle>
<DialogDescription>توضیحات دیالوگ در اینجا قرار میگیرد.</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button type="primary">تأیید</Button>
</DialogFooter>
</DialogContent>
</Dialog>import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogSection,
DialogFooter,
Button,
Input,
} from '@partodata/ui'
;<Dialog>
<DialogTrigger asChild>
<Button>باز کردن دیالوگ</Button>
</DialogTrigger>
{/* `sectioned` هدر/بدنه/فوتر را به آناتومی بخشبندیشدهی استودیویی تبدیل میکند */}
<DialogContent sectioned>
<DialogHeader>
<DialogTitle>ویرایش پروفایل</DialogTitle>
<DialogDescription>اطلاعات خود را ویرایش کرده و ذخیره کنید.</DialogDescription>
</DialogHeader>
<DialogSection className="space-y-3">
<Input placeholder="نام کامل" defaultValue="مریم محمدی" />
<Input placeholder="ایمیل" type="email" defaultValue="maryam@example.com" />
</DialogSection>
<DialogFooter>
<Button variant="outline">لغو</Button>
<Button>ذخیره</Button>
</DialogFooter>
</DialogContent>
</Dialog>حالتها و انواع
دیالوگ پایه
ساختار کامپوننتها
<Dialog>
<DialogTrigger asChild>
<Button>باز کردن</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>عنوان</DialogTitle>
<DialogDescription>توضیحات</DialogDescription>
</DialogHeader>
{/* محتوا */}
<DialogFooter>
<Button>تأیید</Button>
</DialogFooter>
</DialogContent>
</Dialog>آناتومی بخشبندیشده (Sectioned)
با افزودن prop بهنام sectioned روی DialogContent، دیالوگ به ساختار بخشبندیشدهی الهامگرفته از Supabase Studio تبدیل میشود: نوار عنوان آرام که با یک خط مویی از بدنه جدا میشود، بدنهی paddingدار درون DialogSection، و فوتر با خط جداکنندهی بالایی و دکمههای ترازشده به انتها. عنوان در این حالت هماندازهی حالت پیشفرض (text-base) اما با وزن پررنگتر (font-medium) نمایش داده میشود.
بدون sectioned، دیالوگ دقیقاً مثل قبل (padding یکنواخت و عنوان با وزن معمولی text-base font-normal) رندر میشود؛ این prop افزایشی است و رفتار مصرفکنندگان فعلی را تغییر نمیدهد.
override کردن استایلهای sectioned
در حالت sectioned، استایلهای داخلی از سلکتور [[data-sectioned]_&] روی Header/Title/Footer اعمال میشوند. این
سلکتور specificity برابر (0,2,0) دارد و بر یک utility سادهی Tailwind (specificity (0,1,0)) در className غلبه
میکند. برای override کردن، یا از همان فرمِ سلکتور ([[data-sectioned]_&]:...) استفاده کنید، یا مقادیر پیشفرضِ
sectioned را بپذیرید.
<DialogContent sectioned>
<DialogHeader>
<DialogTitle>ویرایش پروفایل</DialogTitle>
<DialogDescription>اطلاعات خود را ویرایش کرده و ذخیره کنید.</DialogDescription>
</DialogHeader>
<DialogSection className="space-y-3">
<Input placeholder="نام کامل" />
<Input placeholder="ایمیل" type="email" />
</DialogSection>
<DialogFooter>
<Button variant="outline">لغو</Button>
<Button>ذخیره</Button>
</DialogFooter>
</DialogContent>اندازهها (size)
عرض دیالوگ با prop بهنام size روی DialogContent کنترل میشود. مقدار پیشفرض lg است که با عرض قبلی (max-w-lg) یکسان است.
size | حداکثر عرض |
|---|---|
sm | max-w-sm |
md | max-w-md |
lg (پیشفرض) | max-w-lg |
xl | max-w-xl |
2xl | max-w-2xl |
3xl | max-w-3xl |
<DialogContent size="2xl">{/* … */}</DialogContent>کنترل Programmatic
const [open, setOpen] = React.useState(false)
;<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>
{/* محتوا */}
<Button onClick={() => setOpen(false)}>بستن</Button>
</DialogContent>
</Dialog>ترکیب کامپوننتها
Dialog از اجزای زیر تشکیل شده است:
- Dialog: کانتینر اصلی و مدیریت state
- DialogTrigger: المنت trigger کننده dialog
- DialogContent: محتوای اصلی dialog (props اختیاری
sizeوsectioned) - DialogHeader: هدر dialog
- DialogTitle: عنوان dialog
- DialogDescription: توضیحات dialog
- DialogSection: بلوک بدنهی paddingدار برای حالت بخشبندیشده (بین هدر و فوتر)
- DialogFooter: فوتر با دکمههای عملیاتی
راهنمای استفاده
بکنید
- از
Dialogبرای عملیاتی که نیاز به تمرکز کاربر دارند استفاده کنید - ازAlertDialogبرای تأیید عملیات مخرب (حذف، خروج، پاکسازی) استفاده کنید - ازSheetبرای پنلهای کناری با محتوای بیشتر استفاده کنید
نکنید
- از دیالوگهای تودرتو پرهیز کنید — کاربر را گیج میکند - در دیالوگ فرمهای پیچیده قرار ندهید — بهجای آن از صفحه جداگانه استفاده کنید - دیالوگ را با کلیک روی پسزمینه نبندید اگر داده ذخیرهنشده وجود دارد
جدول ویژگیها
Dialog
DialogContent
DialogSection
دسترسیپذیری
- Focus بهطور خودکار به داخل dialog منتقل میشود
- با فشردن Escape بسته میشود
- Focus trap برای پیمایش کیبورد
- از
role="dialog"وaria-modalاستفاده میشود aria-labelledbyبرای عنوانaria-describedbyبرای توضیحات
ملاحظات RTL
- محتوا بهصورت خودکار راستچین میشود
- دکمه بستن در سمت چپ بالا قرار میگیرد (با inset منطقی
end-4که در RTL به لبهی چپ نگاشت میشود) - ترتیب دکمهها در DialogFooter از راست به چپ است
تعامل با کیبورد
Escape: بستن دیالوگ -Tab: حرکت بین عناصر داخل دیالوگ (فوکوس محبوس در دیالوگ) -Shift + Tab: حرکت معکوس فوکوس- فوکوس هنگام باز شدن به اولین عنصر تعاملی منتقل میشود
کامپوننتهای مرتبط
- AlertDialog — وقتی عمل مخرب است و کاربر باید حتماً تأیید کند (حذف، پاکسازی)
- ConfirmDialog — wrapper سادهتر برای تأییدهای رایج بدون نیاز به سفارشیسازی
- Sheet — وقتی محتوا بلندتر است یا فرم بیش از ۵ فیلد دارد
- Drawer — نسخه موبایلپسند که از پایین صفحه باز میشود