پرتوپرتو

مودالیتی (Modality)

راهنمای انتخاب — دیالوگ در برابر شیت در برابر آلرت‌دیالوگ در برابر کانفرم‌دیالوگ در برابر پاپ‌اور و دراپ‌داون

عناصر مودال کارِ فعلی کاربر را قطع می‌کنند تا ورودی، تصمیم یا توجه متمرکز بخواهند. آن‌ها بالای پشتهٔ بصری ظاهر می‌شوند و (به‌صورت پیش‌فرض) همه‌چیز زیرشان را غیرفعال می‌کنند. به‌خاطر ماهیت به‌شدت قطع‌کننده، مودال‌ها را کم و حساب‌شده به کار ببرید.

موارد رایج استفاده:

  • گرفتن تأیید از کاربر
  • گرفتن یک فرم موقت پیش از تکمیل یک اقدام
  • هشدار یا کندکردن کاربر پیش از یک اقدام مخرب

قاعدهٔ کلی: برای کارهای کوتاه و متمرکز از دیالوگ و برای فرم‌های طولانی‌تر یا نماهای مفصل‌تر از شیت استفاده کنید.

نمونه بصری

پیاده‌سازی

راهنمای انتخاب

موقعیتکامپوننت
تأیید بحرانی، یک پاراگراف کوتاه، تصمیم واضحConfirmDialog یا AlertDialog
اقدام مخرب که نیاز به تأیید تایپی دارد (حذف یک منبع نام‌دار)ConfirmDialog با confirmString
تأییدی که به زمینهٔ اضافه، هشدار یا کنترل ساده نیاز داردConfirmDialog با alert
کار متمرکز و کوتاه با فرم/انتخابگر دلخواهDialog
فرم چندفیلدی، ویرایشگر، پنل تنظیمات، نمای مفصلSheet
انتخاب یا محتوای کمکی سبک، بدون مسدودکردن صفحهPopover
فهرست اقدامات روی یک عنصر (منوی زمینه/اکشن)DropdownMenu

تأیید سادهٔ بحرانی

برای یک تأیید بحرانی که در یک پاراگراف کوتاه توضیح داده می‌شود، AlertDialog یا ConfirmDialog نقطهٔ شروع است.

import { ConfirmDialog, Button } from '@partodata/ui'
;<ConfirmDialog
  trigger={<Button variant="outline">آرشیو کمپین</Button>}
  title="آرشیو این کمپین؟"
  description="کمپین به آرشیو منتقل می‌شود و از فهرست فعال خارج می‌شود."
  confirmLabel="آرشیو"
  onConfirm={archiveCampaign}
/>

الگوهای رایج

آلرت‌دیالوگ — تأیید یا اطلاع بحرانی

AlertDialog برای تأیید یا اطلاع یک اقدام بحرانی با یک تصمیم واضح است. عنوان و متن دکمهٔ تأیید باید با اقدامی که از نقطهٔ ورود شروع شده هم‌خوان باشد.

کانفرم‌دیالوگ با اسلات alert — زمینهٔ اضافه

وقتی تأیید به بیش از یک پاراگراف نیاز دارد (زمینهٔ اضافه یا هشدار پیامدهای برگشت‌ناپذیر)، از اسلات alert استفاده کنید که یک Callout بین سربرگ و فوتر رندر می‌کند.

<ConfirmDialog
  trigger={<Button variant="outline">حذف گزارش</Button>}
  variant="destructive"
  title="حذف گزارش؟"
  description="این گزارش برای همیشه حذف می‌شود."
  alert={{
    title: 'این اقدام برگشت‌ناپذیر است',
    description: 'پس از حذف، امکان بازیابی داده‌های این گزارش وجود ندارد.',
  }}
  confirmLabel="حذف"
  onConfirm={deleteReport}
/>

کانفرم‌دیالوگ با تأیید تایپی — اقدام مخرب

برای اقدامات مخرب و برگشت‌ناپذیر، confirmString یک «دست‌انداز عمدی» اضافه می‌کند: کاربر باید عبارت دقیق را تایپ کند تا دکمهٔ تأیید فعال شود.

<ConfirmDialog
  trigger={<Button variant="destructive">حذف کمپین</Button>}
  variant="destructive"
  title="حذف کمپین «تخفیف فصلی»؟"
  description="همهٔ داده‌های این کمپین برای همیشه حذف می‌شود."
  confirmString="تخفیف فصلی"
  confirmLabel="حذف دائمی"
  onConfirm={deleteCampaign}
/>

دیالوگ عمومی — جریان‌های دلخواه

Dialog یک مودال عمومی برای جریان‌های دلخواه (فرم، انتخابگر، تعامل غیربحرانی که رد کردنش قابل‌قبول است) است.

شیت — فرم‌ها و نماهای مفصل

Sheet یک دیالوگ به‌شکل پنل کناری است. برای محتوایی بزرگ‌تر از چند فیلد یا وقتی یک دیالوگ مرکزی تنگ به نظر می‌رسد از آن استفاده کنید. برای فرم‌های چندبخشی، از prop sectioned استفاده کنید تا سربرگ/بدنه/فوتر با خط جداکننده تفکیک شوند.

پاپ‌اور و دراپ‌داون — غیرمودال و سبک

Popover و DropdownMenu صفحه را مسدود نمی‌کنند و برای محتوای کمکی سبک یا فهرست اقدامات‌اند. اگر انتخاب کاربر بحرانی نیست و نباید کل صفحه غیرفعال شود، این‌ها را به‌جای دیالوگ ترجیح دهید.

بهترین روش‌ها + دام‌های رایج

رد کردن فرم «کثیف» (Dirty form dismissal)

وقتی یک دیالوگ یا شیت شامل فرم است، همهٔ راه‌های عادی رد کردن را فعال نگه دارید (کلیک روی backdrop، کلید Escape، آیکون بستن و دکمهٔ انصراف در فوتر) — اما پیش از دورانداختن تغییرات ذخیره‌نشده، تأیید بگیرید.

جریان تصمیم:

  1. کاربر تلاش می‌کند دیالوگ/شیت را ببندد.
  2. اگر فرم تمیز است (تغییر ندارد)، بلافاصله ببند.
  3. اگر فرم کثیف است، یک دیالوگ تأییدِ دورانداختن نشان بده.
  4. «ادامهٔ ویرایش» به فرم برمی‌گردد.
  5. «دورانداختن تغییرات» می‌بندد و فرم را ریست می‌کند.

چک‌لیست پیاده‌سازی:

  • تلاش‌های بستن را از onOpenChange رهگیری کنید.
  • دکمهٔ انصراف فوتر را هم از همان گارد بستن عبور دهید.
  • یک دیالوگ تأیید جدا برای حالت کثیف رندر کنید.
  • انصراف را غیرمخرب نگه دارید؛ برای خروج یک‌کلیکی مخرب از «دورانداختن» استفاده کنید.
  • فقط تلاش‌های بستنِ کنترل‌شده را گارد کنید؛ سعی نکنید تغییر مسیر یا unmount دلخواه را مسدود کنید.
  • اگر رد کردن مبتنی بر مسیر (route) یا بستن صفحه است، از یک navigation guard استفاده کنید که همان UI تأییدِ دورانداختن را می‌سازد، نه گسترش گاردِ بستنِ دیالوگ/شیت.

پیاده‌سازی نمونه (با AlertDialog):

import * as React from 'react'
import { useForm } from 'react-hook-form'
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
  SheetBody,
  SheetFooter,
  Button,
  ConfirmDialog,
} from '@partodata/ui'

function CampaignEditor({ open, onClose }: { open: boolean; onClose: () => void }) {
  const form = useForm()
  // مقادیر formState را حتماً destructure کنید وگرنه به‌روزرسانی نمی‌شوند
  const { isDirty } = form.formState
  const [discardOpen, setDiscardOpen] = React.useState(false)

  // گاردِ بستن: اگر فرم کثیف است، به‌جای بستن، تأیید دورانداختن را باز کن
  const handleOpenChange = (next: boolean) => {
    if (next) return
    if (isDirty) {
      setDiscardOpen(true)
    } else {
      onClose()
    }
  }

  const discardAndClose = () => {
    form.reset()
    setDiscardOpen(false)
    onClose()
  }

  return (
    <>
      <Sheet open={open} onOpenChange={handleOpenChange}>
        <SheetContent sectioned>
          <SheetHeader>
            <SheetTitle>ویرایش کمپین</SheetTitle>
          </SheetHeader>
          <SheetBody>{/* فیلدهای فرم */}</SheetBody>
          <SheetFooter>
            {/* دکمهٔ انصراف از همان گارد عبور می‌کند */}
            <Button variant="outline" onClick={() => handleOpenChange(false)}>
              انصراف
            </Button>
            <Button onClick={form.handleSubmit(save)}>ذخیره</Button>
          </SheetFooter>
        </SheetContent>
      </Sheet>

      {/* دیالوگ تأییدِ دورانداختن — جدا از شیت */}
      <ConfirmDialog
        open={discardOpen}
        onOpenChange={setDiscardOpen}
        variant="destructive"
        title="دورانداختن تغییرات؟"
        description="تغییرات ذخیره‌نشدهٔ این فرم از دست می‌رود."
        cancelLabel="ادامهٔ ویرایش"
        confirmLabel="دورانداختن تغییرات"
        onConfirm={discardAndClose}
      />
    </>
  )
}

دام‌های رایج

  • مسدودکردن راه‌های خروج: backdrop/Escape/آیکون بستن را غیرفعال نکنید تا کاربر «مجبور» به تصمیم شود؛ به‌جای آن با گاردِ دورانداختن تأیید بگیرید.
  • مودال روی مودال: از باز کردن دیالوگ روی دیالوگ پرهیز کنید؛ اگر تأیید به زمینهٔ بیشتری نیاز دارد، از اسلات alert در ConfirmDialog استفاده کنید.
  • شیت برای یک تأیید کوتاه: برای یک تصمیم یک‌پاراگرافی از شیت استفاده نکنید؛ دیالوگ درست است. شیت برای فرم‌های بلند است.
  • پاپ‌اور برای تصمیم بحرانی: اقدام مخرب یا برگشت‌ناپذیر را در پاپ‌اور نگذارید؛ آن نیاز به مودالِ مسدودکننده و در صورت لزوم تأیید تایپی دارد.

صفحات مرتبط

  • تأیید (الگو) — الگوی کامل تأیید اقدام‌ها
  • AlertDialog — دیالوگ تأیید بحرانی با prop sectioned
  • ConfirmDialog — دیالوگ تأیید با اسلات alert و تأیید تایپی confirmString
  • Dialog — مودال عمومی برای جریان‌های دلخواه
  • Sheet — پنل کناری برای فرم‌ها و نماهای مفصل، با prop sectioned
  • Popover — محتوای کمکی سبک و غیرمودال
  • DropdownMenu — فهرست اقدامات روی یک عنصر