دیالوگ — Dialog
کپی کد یک پنجرهٔ مودال مرکزی است که توجه کاربر را برای یک فرم کوتاه یا یک اطلاعات متمرکز میگیرد. از React Aria برای دام فوکوس، Escape، قفل اسکرول صفحهٔ زیرین، کپی کد پیرامون و بازگرداندن فوکوس به محرک استفاده میکند. این رفتارها ثابتاند و هیچ تم یا پراپی آنها را غیرفعال نمیکند. برای تأیید کنش مخرب از کپی کد، برای تغییر خودکار بین نمای مودال و کشو در موبایل از کپی کد استفاده کنید.
وضعیت: beta · لایه: ۳ (کپی کد) · کد: کپی کد
import { Dialog } from '@tokapps/tuk';نمونهٔ زنده
کد قابل کپی
پایه: محرک، عنوان، توضیح و کنشها
import { Dialog, Button } from '@tokapps/tuk';export function IdeaDialog() { return ( <Dialog trigger={<Button>ثبت ایده</Button>} title="ثبت ایدهٔ جدید" description="ایدهات را کوتاه و روشن بنویس تا جامعه بتواند ارزیابیاش کند." footer={({ close }) => ( <> <Button variant="ghost" onClick={close}>بعداً</Button> <Button onClick={close}>ثبت ایده</Button> </> )} > <p>پس از ثبت، ایده در بخش «در حال بررسی» نمایش داده میشود.</p> </Dialog> );}پیشرفته: کنترلشده، اندازهٔ بزرگ، بدون بستن با پسزمینه و کنش ناهمگام
import { useState } from 'react';import { Dialog, Button } from '@tokapps/tuk';import { submitIdea } from './api'; // تابع ارسال خود اپexport function SubmitIdeaDialog() { const [open, setOpen] = useState(false); return ( <> <Button variant="secondary" onClick={() => setOpen(true)}>باز کردن فرم</Button> <Dialog open={open} onOpenChange={setOpen} size="lg" dismissable={false} title="ثبت ایدهٔ جدید" description="کلیک روی پسزمینه این پنجره را نمیبندد؛ از دکمهها یا Escape استفاده کنید." footer={({ close }) => ( <> <Button variant="ghost" onClick={close}>انصراف</Button> <Button action={async () => { await submitIdea(); close(); }} > ثبت ایده </Button> </> )} > <p>متن ایده را در فیلدهای زیر وارد کنید.</p> </Dialog> </> );}حالت محدود: بدون دکمهٔ بستن، با چاپ قابل نمایش
import { Dialog, Button } from '@tokapps/tuk';export function ProcessNotice() { return ( <Dialog size="sm" showClose={false} print="show" trigger={<Button variant="secondary">وضعیت پردازش</Button>} title="در حال بررسی" footer={({ close }) => <Button onClick={close}>متوجه شدم</Button>} > <p>ایدهات تا ۲۴ ساعت آینده بررسی میشود. این پنجره با «متوجه شدم» یا کلید Escape بسته میشود.</p> </Dialog> );}تعاملها (Dialog = Modal + interaction)
کپی کد امتداد کپی کد است: همهٔ کانفیگهای Modal را میپذیرد و با کپی کد رفتار کاربر را تعیین میکند. هر نوع یک نمونهٔ زنده و یک بلوک کد قابلکپی دارد.
تأیید: انصراف و تأیید
import { Button, Dialog } from '@tokapps/tuk';export function ConfirmDialog() { return ( <Dialog interaction={{ kind: 'confirm', onConfirm: () => undefined, onCancel: () => undefined, confirmLabel: 'ذخیره', cancelLabel: 'انصراف' }} trigger={<Button>ذخیرهٔ تغییرات</Button>} title="ذخیرهٔ تغییرات؟" description="تغییرات این صفحه ذخیره شود." /> );}تأیید خطرناک: alertdialog بدون بستن با پسزمینه
import { Button, Dialog } from '@tokapps/tuk';export function DangerConfirmDialog() { return ( <Dialog interaction={{ kind: 'confirm', tone: 'danger', confirmLabel: 'حذف ایده', onConfirm: () => undefined }} trigger={<Button variant="secondary">حذف ایده</Button>} title="این ایده حذف شود؟" description="این کار بازگشتپذیر نیست. پوشش با پسزمینه بسته نمیشود و نقش alertdialog دارد." /> );}تأیید ناهمزمان: دکمهها تا پایان کنش غیرفعال
import { Button, Dialog } from '@tokapps/tuk';const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));export function AsyncConfirmDialog() { return ( <Dialog interaction={{ kind: 'confirm', confirmLabel: 'ارسال', onConfirm: () => wait(1200) }} trigger={<Button>ارسال با انتظار</Button>} title="ارسال درخواست؟" description="تا پایان ارسال، دکمهها غیرفعال میمانند و پوشش بعد از موفقیت بسته میشود." /> );}فرم: FormData و ارسال با Enter
import { Button, Dialog } from '@tokapps/tuk';export function FormDialog() { return ( <Dialog interaction={{ kind: 'form', submitLabel: 'ثبت ایده', onSubmit: (data) => console.info(data.get('title')) }} trigger={<Button>فرم ثبت ایده</Button>} title="ثبت ایدهٔ جدید" description="عنوان را وارد کن؛ Enter هم فرم را ارسال میکند." > <label style={{ display: 'grid', gap: 'var(--tds-space-1)' }}> عنوان <input name="title" required /> </label> </Dialog> );}فرم بدون بستن پس از ارسال
import { Button, Dialog } from '@tokapps/tuk';const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));export function KeepOpenFormDialog() { return ( <Dialog interaction={{ kind: 'form', closeOnSubmit: false, submitLabel: 'ذخیره و ادامه', onSubmit: () => wait(600) }} trigger={<Button variant="secondary">فرم بدون بستن</Button>} title="ویرایش سریع" > <label style={{ display: 'grid', gap: 'var(--tds-space-1)' }}> یادداشت <input name="note" /> </label> </Dialog> );}انتخاب از فهرست: هر گزینه یک تصمیم
import { Button, Dialog } from '@tokapps/tuk';export function ChoiceDialog() { return ( <Dialog interaction={{ kind: 'choice', onChoose: () => undefined, options: [ { value: 'publish', label: 'انتشار عمومی', description: 'همه میتوانند ببینند.' }, { value: 'draft', label: 'ذخیره بهصورت پیشنویس', description: 'فقط برای تو قابلدیدن است.' }, { value: 'discard', label: 'حذف پیشنویس', tone: 'danger' }, ], }} trigger={<Button>انتخاب وضعیت</Button>} title="این ایده چه وضعیتی داشته باشد؟" /> );}ویزارد چندمرحلهای
import { Button, Dialog } from '@tokapps/tuk';export function WizardDialog() { return ( <Dialog interaction={{ kind: 'wizard', onFinish: () => undefined, steps: [ { id: 'title', title: 'عنوان', content: <input aria-label="عنوان" name="title" /> }, { id: 'body', title: 'شرح', content: <textarea aria-label="شرح" name="body" /> }, { id: 'review', title: 'بازبینی', content: 'همهچیز آماده است؛ پایان را بزن.' }, ], }} trigger={<Button>راهنمای ثبت</Button>} title="ثبت ایده در سه مرحله" /> );}کانفیگهای Modal روی Dialog (ارثبری)
import { Button, Dialog } from '@tokapps/tuk';export function ModalConfigsDialog() { return ( <Dialog glow="ambient" border="rainbow" dock="visible" scrim="dim" placement="top" sound={{ open: 'notify', close: 'tap' }} swipeToDismiss trigger={<Button>همهٔ کانفیگهای Modal</Button>} title="دیالوگ با حالتهای Modal" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>} > هر کانفیگ Modal (glow، border، dock، scrim، placement، motion، sound، swipeToDismiss) روی Dialog هم کار میکند. </Dialog> );}همهٔ پیکربندیها
کپی کد همهٔ پراپهای کپی کد (کپی کد) را میگیرد و فقط کپی کد را اضافه میکند (کپی کد). پیشفرضها از پارامترهای تابع کپی کد در کپی کد خوانده شدهاند.
| پراپ | نوع | پیشفرض | توضیح |
|---|---|---|---|
| کپی کد | کپی کد | — | محرک باز کردن؛ با کپی کد به رویداد press وصل میشود. بدون آن با کپی کد کنترل کنید. |
| کپی کد | کپی کد | — | حالت کنترلشده. |
| کپی کد | کپی کد | — | حالت کنترلنشدهٔ اولیه. |
| کپی کد | کپی کد | — | با هر تغییر باز یا بسته صدا میخورد؛ قبل از آن صدای متناظر (در صورت وجود) پخش میشود. |
| کپی کد | کپی کد | بدون پیشفرض (الزامی) | عنوان؛ نام دسترسی پنجره از آن گرفته میشود. |
| کپی کد | کپی کد | — | توضیح زیر عنوان؛ بهصورت کپی کد وصل میشود. |
| کپی کد | کپی کد | — | ناحیهٔ کنشها؛ با تابع میتوان کپی کد را گرفت. برای کپی کد، کپی کد و کپی کد نادیده گرفته میشود. |
| کپی کد | کپی کد | کپی کد | نوع تعامل: کپی کد · کپی کد (با کپی کد، کپی کد، کپی کد) · کپی کد (با کپی کد) · کپی کد (با کپی کد، کپی کد) · کپی کد (با کپی کد، کپی کد). |
| کپی کد · کپی کد · کپی کد · کپی کد · کپی کد · کپی کد · کپی کد · کپی کد · کپی کد · کپی کد · کپی کد | — | — | همان کانفیگهای Modal؛ جدول کامل در کپی کد. |
| کپی کد | کپی کد | — | بدنهٔ اسکرولپذیر؛ با تابع میتوان کپی کد را گرفت. |
| کپی کد | کپی کد | کپی کد | عرض پنل از کپی کد؛ کپی کد تمامصفحه بدون گوشهٔ گرد و بدون حاشیه (موبایل کوچک). |
| کپی کد | کپی کد | کپی کد | نقش ARIA. تأیید با کپی کد خودکار کپی کد میشود؛ کپی کد هم همان قرارداد را دارد. |
| کپی کد | کپی کد | کپی کد (کپی کد برای تأیید خطرناک) | کپی کد یعنی کلیک روی پرده نمیبندد؛ فقط دکمهها و Escape. |
| کپی کد | کپی کد | کپی کد | نمایش دکمهٔ بستن مرئی در گوشهٔ انتهایی. |
| کپی کد | کپی کد | کپی کد | برچسب دسترسپذیر دکمهٔ بستن. |
| کپی کد | کپی کد | — | مقدار کپی کد روی ریشه؛ برای نشانهگذاری نمای ResponsiveDialog. |
| کپی کد | کپی کد | — | نام دسترسی وقتی عنوان مرئی ندارید. |
| کپی کد | کپی کد | — | مقصد اختصاصی صدا (opt-in). |
| کپی کد | کپی کد | کپی کد | رفتار چاپ؛ کپی کد پنل را ایستا چاپ میکند. |
| کپی کد | کپی کد | از کپی کد | جهت صریح؛ پیشفرض RTL است. |
| کپی کد | کپی کد | — | کلاس اضافه روی ریشهٔ پوشش (کپی کد). |
ساختار و اسلاتها
ترتیب DOM و کپی کد ثابتاند؛ کپی کد، توکنها و استایلهای هویتی فقط ظاهر را تغییر میدهند.
ModalOverlay [data-tds="dialog"][data-overlay="modal"][data-size][data-print]└── Modal [data-part="panel"] └── RacDialog [data-part="dialog"][role] ├── button [data-part="close"] (فقط وقتی showClose) ├── header [data-part="header"] │ └── div [data-part="heading"] │ ├── Heading [data-part="title"] (slot=title) │ └── p [data-part="description"] (فقط وقتی description) ├── div [data-part="body"] (فقط وقتی children) └── footer [data-part="footer"] (فقط وقتی footer)- بنیان ثابت: ترتیب بالا، کپی کد ها، کپی کد، ارتباط کپی کد و کپی کد، و جای دکمهٔ بستن در انتهای خط.
- قابل تغییر: کپی کد روی ریشه، متغیرهای کپی کد، و محتوای کپی کد، کپی کد.
همهٔ حالتها
| حالت | نشانه (data-attribute یا prop) | نمایش |
|---|---|---|
| بسته (closed) | پوشش در DOM نیست | — |
| در حال ورود | کپی کد روی کپی کد و کپی کد (از React Aria) | پرده با fade و پنل با کپی کد، مدت کپی کد |
| باز (open) | کپی کد | پرده و پنل؛ بقیهٔ صفحه کپی کد |
| در حال خروج | کپی کد | fade-out و pop-out |
| پیشفرض (دکمهٔ بستن) | — | شفاف، رنگ کپی کد |
| hover (دکمهٔ بستن) | کپی کد | پسزمینه کپی کد، رنگ کپی کد |
| pressed (دکمهٔ بستن) | کپی کد | پسزمینه کپی کد |
| focus-visible | کپی کد روی دکمهٔ بستن و کنترلهای داخل پنل (نه خود کپی کد) | حلقهٔ کپی کد |
| کپی کد | کپی کد در React Aria | کلیک پرده نمیبندد |
| کپی کد | کپی کد | تمامصفحه، بدون حاشیه و گوشهٔ گرد |
| چاپ | کپی کد | پنل ایستا با حاشیه؛ دکمهٔ بستن پنهان |
| در حال انجام کنش (pending) | کپی کد روی دکمهٔ کنش، کپی کد روی دکمهها | در کپی کد، کپی کد و کپی کد تا پایان Promise کنش؛ موفقیت = بستن، خطا = باز ماندن |
رفتار پوشش (از قرارداد کپی کد در کپی کد)
- دام فوکوس: فوکوس درون پنل حبس میشود. با باز شدن به پنل میرود و با بسته شدن به محرک برمیگردد.
- Escape: بالاترین پوشش را میبندد و کپی کد صدا میخورد.
- پسزمینه: کلیک روی پرده میبندد؛ با کپی کد فقط دکمهها و Escape میبندند.
- قفل اسکرول: اسکرول صفحهٔ زیرین قفل میشود؛ فقط بدنهٔ پنل اسکرول میخورد (کپی کد).
- تودرتو: پوششهای تودرتو با ترتیب DOM روی هم مینشینند؛ Escape یکییکی از بالا میبندد.
- کشیدن برای بستن: اختیاری با کپی کد (از Modal)؛ معادل غیرکشیدنی دکمهٔ بستن مرئی و Escape است.
تغییرات مجاز برای توسعهدهنده
- اندازه (کپی کد): کپی کد، کپی کد (پیشفرض)، کپی کد، کپی کد.
- تعامل (کپی کد): کپی کد (پیشفرض)، کپی کد (با کپی کد برای کنش مخرب)، کپی کد، کپی کد، کپی کد. هر کدام نمونهٔ کد قابلکپی در بخش «تعاملها» دارد.
- کانفیگهای Modal: همهٔ آنها (کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد) روی Dialog هم کار میکنند.
- نقش (کپی کد): کپی کد (پیشفرض) یا کپی کد؛ برای تأیید خطرناک خودکار تنظیم میشود.
- جهت (کپی کد): کپی کد یا کپی کد. این پراپ locale کلیدهای جهتدار React Aria را تنظیم میکند؛ چیدمان پنل از جهت سند (کپی کد) میآید.
- چاپ (کپی کد): کپی کد یا کپی کد.
- دکمهٔ بستن: نمایش (کپی کد) و برچسب (کپی کد) قابل ترجمه.
- پسزمینه (کپی کد): بستن با کلیک روی پرده یا غیرفعال.
- محتوا: کپی کد، کپی کد، کپی کد و کپی کد با گره یا تابع کپی کد.
- کنترل حالت: کپی کد و کپی کد، یا کپی کد و کپی کد.
- نقاط توسعه: کپی کد روی ریشه، کپی کد (کپی کد)، متغیرهای کپی کد در سطح پوشش (فهرست در بخش توکنها)، کپی کد، و پیامهای قابل ترجمه (کپی کد، کپی کد، کپی کد و متن کنشها).
تغییرات ممنوع (بنیان ثابت)
- تغییر ترتیب DOM یا حذف کپی کد های کپی کد، کپی کد، کپی کد، کپی کد، کپی کد.
- دور زدن دام فوکوس یا Escape و حذف کپی کد رفتار پوشش.
- تأیید خطرناک (کپی کد) با بستن از پسزمینه یا بدون نقش کپی کد.
- حذف کپی کد (پراپ الزامی؛ نام دسترسی پوشش است).
- کوچکتر از ۴۴px کردن دکمهٔ بستن: اندازه از کپی کد و آن از کپی کد میآید.
- استایل خام (hex، rgb، gradient) برای پسزمینه یا حاشیه. فقط توکنهای معنایی و کپی کد.
- وابستگی به مسیر asset یا آیکون خارج از کپی کد.
RTL، کیبورد و صفحهخوان
- RTL: جهت پیشفرض RTL است. در رندر اول کپی کد فرض میشود و در effect از کپی کد خوانده میشود (کپی کد). ویژگیهای منطقی (کپی کد/کپی کد) استفاده شدهاند؛ دکمهٔ بستن در کپی کد است و در RTL به سمت چپ میرود.
- کلیدها: کپی کد و کپی کد فوکوس را درون پنل میچرخانند؛ کپی کد میبندد؛ کپی کد کنترل فوکوسدار را فعال میکند. کلیدهای جهتدار با locale همان جهت (کپی کد برای RTL) رفتار میکنند.
- صفحهخوان: نام پنل از عنوان (کپی کد) و توضیح از کپی کد (کپی کد) میآید؛ باز شدن با انتقال فوکوس اعلام میشود.
- هدف لمسی: دکمهٔ بستن حداقل ۴۴px است.
- کنتراست: روشن، تیره و کنتراست بالا با کپی کد بررسی میشوند.
صدا، حرکت، چاپ و کاهش حرکت
- صدا: پیشفرض بیصداست (opt-in). با کپی کد یا مقصد سراسری (کپی کد در کپی کد) فعال میشود. باز شدن و بسته شدن هر دو کپی کد هستند؛ هیچ صدایی روی hover پخش نمیشود. معادل بصری: ظاهر شدن پنل و انتقال فوکوس. صدا فقط با تعامل صریح کاربر پخش میشود.
- حرکت: نام معنایی کپی کد (opacity و scale) برای پنل و کپی کد (opacity) برای پرده در کپی کد. زمان و منحنی از کپی کد و کپی کد میآید.
- کاهش حرکت: با کپی کد یا کپی کد (وقتی کپی کد نباشد) انیمیشن و transition حذف میشود و پوشش فوری ظاهر و پنهان میشود.
- چاپ: پیشفرض کپی کد (پوشش در چاپ پنهان است). با کپی کد پنل ایستا، تکرنگ و با حاشیه چاپ میشود و دکمهٔ بستن پنهان است.
توکنها
فایل توکنهای مصرفی: کپی کد. مقدار مرجع همهٔ کپی کد در فایل مشترک کپی کد است.
- معنایی: کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد.
- کامپوننتی: کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد.
- تایپوگرافی، کنترل و مقیاس: کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد.
قرارداد ARCH
- آیکون دکمهٔ بستن فقط با کپی کد و نام معنایی است؛ مسیر asset در کد وجود ندارد.
- تم فقط حرکت (کپی کد، کپی کد) و توکنها را تغییر میدهد؛ ساختار و رفتار پوشش ثابت است.
- این کامپوننت gesture ندارد؛ کشیدن برای بستن عمداً تعریف نشده است.
نکات
- برای تأیید کنش مخرب یا بازگشتناپذیر: دیالوگ تأیید — AlertDialog.
- برای تغییر خودکار مودال به کشو در موبایل: ResponsiveDialog.
- برای محتوای کوچک کنار محرک بدون پرده: Popover. برای پنل کناری: Drawer.