Skip to main content

الگوها

کامپوننت‌ها «چه شکلی» را پاسخ می‌دهند؛ الگوها «چطور کار می‌کند» را. هر الگو یک مسئلهٔ تکرارشوندهٔ واقعی محصول را با ترکیبی از کامپوننت‌ها حل می‌کند — و در اپ مرجع همین الان در حال اجراست.

۱. کلاس‌های پنجره — ناوبری واکنش‌گرا

یک DOM، سه چیدمان ناوبری بر اساس عرض نمایشگر (کلاس‌های پنجرهٔ MD3). هیچ نسخهٔ جداگانه‌ای برای موبایل وجود ندارد؛ فقط CSS عوض می‌کند.

کلاسعرضناوبرینمای اولیهایجاد
compact<۶۰۰نوار پایین ۵تایی + FAB + کشوی بیرون‌از‌صفحهبرنامه (فشرده)فقط FAB و کلید N
medium۶۰۰–۱۰۲۳ریل آیکونی ۸۰px + FAB + کشو از دکمهٔ منوبرنامهFAB + ریل
expanded+≥۱۰۲۴سایدبار دائمی ۲۶۴px (سمت راست) + دکمهٔ ایجاد در سایدبارماهدکمهٔ سایدبار + کلید N

لبهٔ expanded در production وب ۱۰۲۴px است — هم‌راستا با lg در tailwind.config.js، useIsMobile و منطق نمای اولیه (مختصات دقیق در UI واکنش‌گرا و وضعیت پذیرش). پروتوتایپ‌های HTML فعلاً لبهٔ ۸۴۰px را نشان می‌دهند — رفتارِ تجربی، نه قرارداد.

✅ نمای فعال و تاریخ جاری در localStorage ذخیره و بازیابی می‌شود · عمق لایهٔ ناوبری: نوار پایین/ریل ← کشو/سایدبار ← دیالوگ، هر عمق فقط یک‌بار. ❌ هم‌زمان نوار پایین و ریل؛ یا سایدبار باز و کشو روی هم · مخفی‌کردن اکشن ایجاد در هیچ کلاسی (فقط جایش عوض می‌شود).

۲. پیش‌نمایش سپس ویرایش

کلیک روی هر رویداد، وظیفه یا تقویم، دیالوگ را در حالت نمایش باز می‌کند: همهٔ داده‌ها فقط‌خواندنی، سریع‌الاسکن، بدون خطر تغییر تصادفی. کاربر با دکمهٔ «ویرایش» به فرم می‌رسد. مسیر «ایجاد» مستقیم به فرم می‌رود — پیش‌نمایش برای موجودهاست.

گاممحتوااکشن‌ها
۱ · کلیکروی چیپ رویداد، ردیف وظیفه، نتیجهٔ جستجو یا کارت تقویم
۲ · نمایشعنوان + تاریخ کامل جلالی (تعطیلی/جمعه قرمز) + ساعت یا «تمام‌روز» + تقویم با نقطهٔ رنگ + نوع + مکان + مهمان‌ها + یادداشتحذف (مخرب) · ویرایش (اصلی و تنها)
۳ · ویرایشهمان دیالوگ با فرم پیش‌پر؛ فوکوس روی عنوانذخیره · انصراف · حذف

جابه‌جایی حالت با یک اتریبیوت روی دیالوگ — بدون بستن/بازکردن مجدد:

<div class="dialog" data-mode="view|edit">
<!-- view: سطرهای فقط‌خواندنی + دکمهٔ ویرایش -->
<!-- edit: فرم پیش‌پر + ذخیره/انصراف -->
</div>

✅ در حالت نمایش فقط یک دکمهٔ اصلی («ویرایش»)؛ حذف در سمت مقابل · Enter = ویرایش، Esc = بستن، تغییر حالت بدون پرش چیدمان. ❌ بازشدن مستقیم فرم ویرایش روی کلیک ساده · دو مرحلهٔ اضافی (نمایش ← «ادامه» ← فرم خالی) — پیش‌نمایش باید کامل باشد.

۳. دیالوگ‌ها، برگه‌ها و منوها

لایهابزارچه زمانی
۱ · منو.menuاکشن‌های فرعی یک لنگر — بدون محتوای فرمی
۲ · پاپ‌آور انتخاب تاریخ.dpopزیر قرص تاریخ؛ Esc اول این را می‌بندد، بعد دیالوگ را
۳ · دیالوگ/برگه.dialogایجاد/نمایش/ویرایش رویداد و وظیفه، تعارض‌ها، رزرو
۴ · توست.toastنتیجهٔ عمل — بدون قطع‌کردن جریان

قواعد مشترک: اسکریم ۴۵٪ + بلور ۳px؛ کلیک روی اسکریم = بستن (به‌جز وقتی فرم کثیف است: اول تأیید) · قفل اسکرول بدنه و محبوس‌کردن فوکوس؛ فوکوس به عنصر محرک برمی‌گردد · حذفِ قابل‌بازگردانی به‌جای دیالوگ تأیید، توستِ «بازگردانی» می‌دهد · هم‌زمان فقط یک لایه از هر عمق.

۴. انتخاب تاریخ جلالی

پاپ‌آور ۲۷۲px که از قرص تاریخ باز می‌شود — همان شبکهٔ ماه، با رفتار کامل تقویمی.

قاعدهجزئیات
لنگر و هالهبازشدن پاپ‌آور، قرصِ تاریخ را با .open روشن نگه می‌دارد
ناوبری ماهشورون‌های RTL: «قبلی» سمت راست؛ کلیک روی عنوان = انتخاب ماه/سال سطح بالا
پاورقی«امروز» همیشه؛ «پاک کردن» فقط برای تاریخ‌های اختیاری (موعد وظیفه)
کیبوردفلش‌ها روز به روز جابه‌جا می‌کنند؛ رد شدن از سرِ هفته، ماه را عوض می‌کند
اعتبارروشن/تعطیل فقط رنگ است، نه غیرفعال — هر روزی قابل انتخاب است

۵. فرم‌ها

قاعدهجزئیات
ترتیب فیلدهااز مهم به جزئی: عنوان ← تقویم ← نوع ← شروع/پایان ← تمام‌روز ← مکان ← مهمان‌ها ← یادداشت
ستون واحدفرم‌ها همیشه تک‌ستونه؛ فقط شروع/پایان دو قرص هم‌عرض در یک سطر گرید ۲تایی
اعتبارسنجیزنده اما بی‌سروصدا: خطا بعد از تعامل کاربر ظاهر می‌شود، نه حین تایپ اول
پیام خطاعلت + راه‌حل: «پایان نمی‌تواند قبل از شروع باشد» — نه «مقدار نامعتبر»
CTAغیرفعال تا اعتبار کامل؛ بعد از ارسال، متن با اسپینر عوض می‌شود و دکمه قفل می‌ماند
ارقامورودی عددی (تلفن، OTP) با direction:ltr + تبدیل ارقام فارسی به لاتین هنگام خواندن (J.en)
Enterفرم تک‌فیلدی (تلفن، جستجو) = ارسال؛ فرم کامل = هیچ (جلوگیری از ثبت تصادفی)

۶. استیت‌های داده

هر سطح داده سه استیت دارد و همه باید طراحی شوند:

استیتنمایشقاعده
بارگذاریاسپینر وسط ناحیه؛ شبکه‌های بزرگ اسکلتون‌گونه با سلول‌های سطح ۱کمتر از ۳۰۰ms هیچ‌چیز نشان نده — پرش استیت نریزان
خالیپیام کوتاه + اکشن ایجاد: «فعلاً کاری نیست» / «رویدادی در این روز نیست»هر تب و نما رشتهٔ خالی مخصوص خودش را دارد؛ هیچ «—» یا باکس خالی
خطاپیام + «تلاش دوباره»؛ لیست‌های مهم تاریخ آخرین موفقیت را نگه می‌دارندخطای شبکه دیتای قبلی را پاک نمی‌کند
همه‌پنهانوقتی همهٔ تقویم‌ها از دید خارج‌اند: راهنمای برگرداندن به‌جای گرید خالیمحتوا باید خودش علت خالی‌بودنش را بگوید

۷. همگام‌سازی و تعارض

همگام‌سازی پس‌زمینه‌ای است و وقتی خوب کار می‌کند دیده نمی‌شود.

  • پیش‌فرض ساکت: موفقیت همگام‌سازی نه بنر دارد نه توست؛ آخرین زمان همگام‌سازی فقط در جایگاه کم‌رنگ تنظیمات.
  • تعارض = تنها استیت پرهیاهو: بنر کهربایی زیر نوار بالا ← دیالوگ فهرست تعارض‌ها با عنوان، فیلد تغییرکرده و دو تصمیم: «نگه‌داشتن نسخهٔ این دستگاه» / «بازگردانی نسخهٔ سرور».
  • تصمیم هر آیتم مستقل است؛ بعد از تصمیم آخرین آیتم، بنر به‌تنهایی جمع می‌شود.
  • حالت آفلاین: کار بدون وقفه ادامه دارد؛ تعارض‌ها هنگام بازگشت اتصال حل می‌شوند.

۸. جستجو

جعبهٔ جستجوی نوار بالا: از حالت فشرده با فوکوس باز می‌شود و نتایج زنده زیر خودش می‌آورد.

رفتارجزئیات
محدودهعنوان، مکان، مهمان و یادداشت رویدادها و وظایف — از امروز به بعد و عقب
نتیجهسطر با عنوان + نقطهٔ رنگ تقویم + تاریخ کامل جلالی (تعطیلی قرمز)؛ کلیک = پرش به آن روز در نمای ماه و باز شدن پیش‌نمایش
بدون نتیجه«چیزی برای "…" پیدا نشد» + پیشنهاد کوتاه‌ترکردن عبارت
کیبورد/ فوکوس روی جستجو · فلش بالا/پایین در نتایج · Enter انتخاب · Esc بستن

۹. حالت تاریک

حالت تاریک تعویض توکن است، نه طرح دوم: data-theme="dark" روی ریشه و همه‌چیز خودش درست می‌شود.

قاعدهجزئیات
برندآبی پرکنتراست پایین می‌آید (#8FB4FF) و متن دکمه تیره می‌شود
تعطیلاتقرمز #D41317 در تاریک به #FF8A80 روشن می‌شود تا روی سطح تیره بخواند
رویدادهاپالت ۸رنگی با color-mix روی سطح تیره روشن می‌شود؛ پس‌زمینهٔ چیپ‌ها همان ۱۳٪ رنگ می‌ماند
سایه‌هادر تاریک عمیق‌تر و اسکریم تا ۵۸٪ — عمق باید حفظ شود
ماندگاریانتخاب کاربر در localStorage ذخیره و بین همهٔ صفحه‌های وب مشترک است — پیاده‌سازی فعلی وب: کلاس .dark + darkMode: 'selector' با کلید darkMode و fallback اولیه از prefers-color-scheme (وضعیت پذیرش)

آزمون شبانه: هر صفحه/کامپوننت جدید باید در هر دو پوسته بازبینی شود — دکمهٔ خورشید/ماه همین مستندات بهترین جای آزمون است.

۱۰. دسترس‌پذیری و نوشتار رابط

نقشهٔ کیبورد

کلیدعمل
→ / ←ماه بعد/قبل (در RTL جهت‌ها طبیعی تقویم‌اند)
↑ / ↓هفته بعد/قبل در نمای ماه
Tپرش به امروز
Nایجاد رویداد/وظیفه (بر اساس نمای فعال)
/فوکوس روی جستجو
Escبستن به ترتیب عمق: تاریخ‌یاب ← منو ← دیالوگ

حداقل‌های غیرقابل مذاکره

  • کنتراست متن ≥ ۴٫۵:۱ در هر دو پوسته؛ هاور هرگز متن را کم‌کنتراست‌تر نمی‌کند.
  • :focus-visible حلقهٔ ۲px برند روی هر عنصر قابل فوکوس — بدون حذف outline.
  • هدف لمسی ≥ ۴۴px؛ دکمه‌های آیکونی همیشه aria-label فارسی دارند.
  • prefers-reduced-motion همهٔ انیمیشن‌ها را خاموش می‌کند.
  • نقش‌های ARIA وضعت‌دار: role="checkbox/switch/dialog" + aria-checked.

نوشتار رابط

اصلدرستغلط
روشن و بدون اغراقهمگام‌سازی با خطا مواجه شداوه! یک اتفاق غیرمنتظره افتاد!!
اصطلاح واحد محصولتقویم · رویداد · وظیفه · موعدتققیم · قرار ملاقات · ددلاین
ارقام فارسی همه‌جا۷ شهریور · ۰۹:۳۰7 شهریور · 09:30
فعل دوم‌شخص مستقیمرویداد حذف شد — بازگردانیعملیات حذف با موفقیت انجام گرفت