پرتوپرتو

دیالوگ (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حداکثر عرض
smmax-w-sm
mdmax-w-md
lg (پیش‌فرض)max-w-lg
xlmax-w-xl
2xlmax-w-2xl
3xlmax-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

Prop

Type

DialogContent

Prop

Type

DialogSection

Prop

Type

دسترسی‌پذیری

  • 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 — نسخه موبایل‌پسند که از پایین صفحه باز می‌شود