Modal — مودال «سیالِ داک»
مودال مثل یک مادهی سیال از داک شیشهای پایین صفحه جدا میشود (قطره، گردنِ کشیده، چکیدن)، بالا میآید و باز میشود تا شبیه مودال شود؛ پسزمینه مثل هر مودال معمولی سفیدِ مهآلود میشود و هنگام بستهشدن دوباره به همان داک تزریق میشود. این رفتار ثابت بنیان است و در همهٔ قالبها یکسان اجرا میشود.
وضعیت: beta · لایه: ۳ (کپی کد) · فراداده: کپی کد
import { Modal } from '@tokapps/tuk/overlays';نمونهٔ زنده
برای دیدن حرکت، دکمه را بزنید و مودال را با Escape یا دکمهٔ بستن ببندید؛ مبدأ و مقصد همین داک پایین صفحه است.
حرکت ثابت
- باز شدن (pour): خودِ داک سیال میشود: تنِ شیشهایاش مایعِ همرنگ میشود (داک واقعی پنهان میشود)، قطرهای از همان تن کنده میشود، تنِ داک در قطره تخلیه میشود، گردنی بین آنها کشیده و باریک میشود و میچکد؛ قطره بالا میآید و به اندازهٔ مودال باز میشود. وقتی رسید، پنل مات ظاهر میشود و مایع زیرش محو میشود.
- پسزمینه: سفیدِ مهآلود (در حالت تیره، تیرهٔ مهآلود) مثل هر مودال معمولی.
- بستن (inject): همان مسیر، معکوس: پنل محو میشود، مایع جمع میشود، گردن دوباره شکل میگیرد، تنِ داک پر میشود و داک واقعی با موج کوتاهی برمیگردد.
- اگر داک پنهان یا ناموجود باشد، نوار فرضی پایین صفحه جای آن را میگیرد. در کاهش حرکت لایهٔ مایع حذف میشود و فقط ظاهر/ناپدید شدن فوری میماند.
- تمها و لایهها فقط زمان و منحنی را با کپی کد، کپی کد، کپی کد و کپی کد تنظیم میکنند؛ مسیر و مقصد قابلتغییر نیست.
حالتها — دست توسعهدهنده باز است
مسیر حرکت مایع (جدا شدن از داک و تزریق به آن) ثابت است؛ اما توسعهدهنده با چند prop ساده «حالت» را انتخاب میکند و همه با هم ترکیب میشوند. هر نمونه زنده است: دکمه را بزنید.
| prop | مقدارها | پیشفرض |
|---|---|---|
| کپی کد | کپی کد · کپی کد | کپی کد |
| کپی کد | کپی کد · کپی کد · کپی کد | کپی کد |
| کپی کد | کپی کد · کپی کد · کپی کد · کپی کد | کپی کد |
| کپی کد | کپی کد · کپی کد · کپی کد | کپی کد |
| کپی کد | کپی کد · کپی کد | کپی کد |
| کپی کد | کپی کد · کپی کد | کپی کد |
| کپی کد | کپی کد · رویداد · کپی کد | کپی کد / کپی کد |
| کپی کد | کپی کد | کپی کد |
import { Button } from '@tokapps/tuk/controls';import { Modal } from '@tokapps/tuk/overlays';پایه (پیشفرض)
مایع از داک جدا میشود، پسزمینه سفیدِ مهآلود و داک مادهاش را به مودال میدهد.
<Modal trigger={<Button>باز کردن مودال</Button>} title="ثبت ایدهٔ جدید" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> پس از ثبت، ایده در بخش «در حال بررسی» نمایش داده میشود.</Modal>بازتاب نرم رنگ تم (Glow)
از پشت مودال، لکههای تاری از رنگهای تم آرام میرقصند. بسیار کمرنگ است تا تمرکز را نگیرد؛ رنگها از توکنهای کپی کد (پیشفرض: رنگهای اکسنت تم) میآیند و با کاهش حرکت ثابت میایستند.
<Modal glow="ambient" trigger={<Button>با بازتاب تم</Button>} title="تمرکز بدون حواسپرتی" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> رنگ پشت مودال از تم فعلی میآید؛ تم را عوض کنید و دوباره باز کنید.</Modal>حاشیهٔ رنگینکمانی (ایستا)
دور کادر مودال یک حاشیهٔ هفترنگ از primitive کپی کد مینشیند (تنها راه مجاز گرادیان). فقط برای مودالهای شاخص استفاده کنید.
<Modal border="rainbow" trigger={<Button>حاشیهٔ رنگینکمان</Button>} title="لانچ محصول" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> مودالی که باید دیده شود.</Modal>حاشیهٔ رنگینکمانی (متحرک)
همان حاشیه، با چرخش آرام. با کپی کد میایستد و در کنتراست بالا تکرنگ میشود.
<Modal border="rainbow-animated" trigger={<Button>رنگینکمان متحرک</Button>} title="کمپین ویژه" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> حاشیه آرام میچرخد.</Modal>داک دیده میشود
داک شیشهای دقیقاً همانطور که هست دیده میشود و هیچ تغییری نمیکند (نه شکل، نه سایه، نه ارتفاع)؛ پرده جای داک سوراخ میشود. فقط قطره: تلّی همرنگ روی لبهٔ بالای داک برمیآید، گردنش کشیده میشود و قطره میچکد؛ هنگام بستن به همان لبه برمیگردد.
<Modal dock="visible" trigger={<Button>داک دیده شود</Button>} title="داک در دید" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> داک زیر مودال کاملاً دیده میشود و مایع از آن بیرون میآید.</Modal>داک پشت پرده است
داک سر جای خودش زیر پردهٔ سفید میماند و کمرنگ دیده میشود؛ مودال پشت داک نمیپرد.
<Modal dock="behind" trigger={<Button>داک پشت پرده</Button>} title="داک پشت" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> داک زیر پرده است و محو دیده میشود.</Modal>داک ناپدید میشود
هنگام باز بودن مودال داک کاملاً پنهان است و پس از بستن با موج برمیگردد؛ مایع همچنان از جای داک جدا میشود.
<Modal dock="hidden" trigger={<Button>داک ناپدید</Button>} title="داک پنهان" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> تا بسته نشود داک دیده نمیشود.</Modal>پردهٔ تیره (کلاسیک)
بهجای سفیدِ مهآلود، پردهٔ تیرهٔ معمولی مودالها.
<Modal scrim="dim" trigger={<Button>پردهٔ تیره</Button>} title="تأیید نهایی" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> پسزمینه تیره میشود.</Modal>بدون پرده
پرده و تاری پسزمینه حذف میشود؛ مودال روی صفحهٔ زنده مینشیند.
<Modal scrim="clear" trigger={<Button>بدون پرده</Button>} title="یادداشت سریع" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> صفحهٔ زیر همچنان دیده میشود.</Modal>نشستن بالای صفحه
مثل پالت فرمان: مودال بالای صفحه مینشیند؛ مایع مقصد را خودش اندازه میگیرد.
<Modal placement="top" trigger={<Button>نشستن در بالا</Button>} title="جستجوی سریع" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> مودال زیر لبهٔ بالا مینشیند.</Modal>محو ساده (بدون مایع)
کنارگذاشتن صریح حرکت مایع توسط توسعهدهنده: فقط محو و بزرگشدن کم. داک دستنخورده میماند.
<Modal motion="fade" trigger={<Button>محو ساده</Button>} title="حرکت ساده" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> بدون مایع و بدون تماس با داک.</Modal>همراه با صدا
هنگام باز و بسته شدن صدا پخش میشود. کپی کد میتواند کپی کد، یک رویداد یا کپی کد باشد. صدا فقط با تعامل کاربر و در صورت روشنبودن صدای کاربر پخش میشود (Opt-in).
<Modal sound={{ open: 'notify', close: 'tap' }} trigger={<Button>با صدا</Button>} title="اعلان مهم" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> باز شدن «notify» و بسته شدن «tap» پخش میشود.</Modal>بستن با ژست کشیدن
هدر را به پایین بکشید تا مودال بسته (و به داک تزریق) شود. معادل بدون ژست: دکمهٔ بستن (همیشه نمایش داده میشود)، Escape و کلیک پسزمینه.
<Modal swipeToDismiss trigger={<Button>بستن با کشیدن</Button>} title="کشیدن به پایین" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> هدر را بگیرید و به پایین بکشید.</Modal>ترکیب امضا
Glow + حاشیهٔ رنگینکمانی + ژست بستن + صدای موفقیت؛ مثالی از ترکیب آزاد حالتها.
<Modal glow="ambient" border="rainbow" swipeToDismiss sound="success" trigger={<Button>ترکیب امضا</Button>} title="تبریک!" footer={({ close }) => <Button onClick={close}>فهمیدم</Button>}> همهٔ حالتها با هم قابل ترکیباند.</Modal>قابلتغییر توسط هر لایه
- اسلاتها: کپی کد، کپی کد، کپی کد، کپی کد (تابع، کپی کد را میگیرد). کپی کد همیشه نام دسترسی است، حتی وقتی کپی کد جای آن را در ظاهر میگیرد.
- رنگبندی و ظاهر: با بازنویسی توکنها: کپی کد، کپی کد، کپی کد، کپی کد، کپی کد، کپی کد و …
- رنگ مایع با کپی کد (پیشفرض همان رنگ پنل) و پردهٔ پسزمینه با کپی کد تنظیم میشود.
چه وقت استفاده کنیم
- فرم یا اطلاعات کوتاهی که باید تمام توجه را بگیرد
- صفحهای که Dock شیشهای دارد (همهٔ سایتهای توکاپس)
چه وقت نه
- تأیید کنش مخرب (از AlertDialog)
- پنل کشویی کناری (از Drawer)
- مودال ساده بدون پیوند با داک (از Dialog)
رفتار کیبورد، صفحهخوان و RTL
- کپی کد/کپی کد فقط درون مودال میچرخد؛ کپی کد میبندد و تزریق به داک آغاز میشود؛ کلیک پسزمینه میبندد (مگر کپی کد)؛ فوکوس به محرک برمیگردد.
- کپی کد با کپی کد از عنوان و کپی کد از توضیح؛ حرکت تزئینی است.
- ویژگیها منطقیاند (دکمهٔ بستن در کپی کد)؛ مسیر حرکت عمودی است و به جهت وابسته نیست.
- چاپ: پیشفرض پنهان؛ با کپی کد پنل ایستا چاپ میشود. صدا: کپی کد/کپی کد فقط opt-in.
API
| پراپ | توضیح |
|---|---|
| کپی کد / کپی کد / کپی کد / کپی کد | محرک یا کنترلشده |
| کپی کد | عنوان؛ نام دسترسی (الزامی) |
| کپی کد | توضیح زیر عنوان |
| کپی کد / کپی کد / کپی کد | اسلاتهای اسکلت؛ کپی کد یا کپی کد |
| کپی کد | عنصر ابتدای هدر پیشفرض |
| کپی کد | کپی کد · کپی کد · کپی کد |
| کپی کد / کپی کد / کپی کد | رفتار بستن |
| کپی کد | انتخابگر داک مبدأ/مقصد (پیشفرض کپی کد) |
| کپی کد / کپی کد / کپی کد / کپی کد | صدا، چاپ، جهت، کلاس |
جزئیات: کپی کد.
نمونهٔ قابلکپی
کد زیر همان کپی کد است و مستقیم در پروژه قابل استفاده است.
import { useState } from 'react';import { Button } from '@tokapps/tuk/controls';import { Modal } from '@tokapps/tuk/overlays';const actions = ({ close }: { close: () => void }) => ( <> <Button variant="ghost" onClick={close}>بعداً</Button> <Button onClick={close}>ثبت ایده</Button> </>);/** نمونههای قابلکپی — مصرفشده در مستندات، Storybook و MCP (get_component_code) */export const modalExamples = { basic: () => ( <Modal trigger={<Button>ثبت ایده</Button>} title="ثبت ایدهٔ جدید" description="ایدهات را کوتاه و روشن بنویس تا جامعه بتواند ارزیابیاش کند." footer={actions}> <p>پس از ثبت، ایده در بخش «در حال بررسی» نمایش داده میشود.</p> </Modal> ), customSlots: () => ( <Modal trigger={<Button variant="secondary">اسکلت سفارشی</Button>} title="گزارش هفتگی" header={<strong>گزارش هفتگی · هفتهٔ ۴۱</strong>} footer={({ close }) => <Button onClick={close}>فهمیدم</Button>} > هدر، بدنه و فوتر نقطههای تغییر استاندارد هستند؛ حرکت از و به داک ثابت میماند. </Modal> ), sizes: () => ( <> <Modal size="sm" trigger={<Button variant="secondary">کوچک</Button>} title="مودال کوچک">متن کوتاه.</Modal> <Modal size="lg" trigger={<Button variant="secondary">بزرگ</Button>} title="مودال بزرگ">محتوای گستردهتر برای فرمهای چندستونه.</Modal> </> ), controlled: function Controlled() { const [open, setOpen] = useState(false); return ( <> <Button onClick={() => setOpen(true)}>باز کردن کنترلشده</Button> <Modal open={open} onOpenChange={setOpen} title="مودال کنترلشده">وضعیت باز/بسته در اختیار والد است؛ بستنِ والد هم به داک تزریق میکند.</Modal> </> ); }, themed: () => ( <div style={{ '--tds-modal-header-bg': 'var(--tds-accent-subtle)', '--tds-modal-footer-bg': 'var(--tds-surface-sunken)' } as React.CSSProperties}> <Modal trigger={<Button variant="secondary">رنگبندی سفارشی</Button>} title="با توکنهای خودت" footer={actions}> رنگ هدر و فوتر فقط با بازنویسی توکنهای <code>--tds-modal-*</code> عوض میشود. </Modal> </div> ),} as const;آزمون و پیشنمایش
- Storybook: کپی کد (کپی کد).
- تست واحد: کپی کد.