You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

4.0 KiB

هدف

اسلاید بین سوالات مثل ریلز اینستاگرام / شورتز یوتیوب: محتوا 1:1 با انگشت حرکت کند، رها کردن بر اساس سرعت (flick) یا مسافت یا commit به بعدی/قبلی یا برگشت، rubber-band در دو انتها، و انیمیشن قابل مقطوع‌سازی (grab mid-animation).

تغییرات — فقط src/components/Componentes/question-snap-list.tsx

1. لایه‌ی درگ با دنبال کردن انگشت (بدون re-render در هر فریم)

  • در touchstart: ثبت نقطه/زمان شروع + ارتفاع کانتینر. اگر لمس روی کنترل‌های تعاملی شروع شود (input, textarea, select, [contenteditable], [data-snap-drag-ignore]) درگ فعال نمی‌شود تا با تایپ/اسلایدر تداخل نکند.
  • در touchmove بعد از عبور از آستانه ~۱۰px: اعمال مستقیم transform روی سه پنل (فعال، بعدی، قبلی) از طریق ref (بدون state ری‌اکت) → 60fps:
    • فعال: translateY(-offset) — بالا می‌رود با انگشت
    • بعدی: translateY(height - offset) — از پایین به‌صورت پنل کامل وارد می‌شود
    • قبلی: translateY(-height - offset) — از بالا وارد می‌شود
  • Rubber-band: در سوال اول/آخر، آفست با ضریب مقاومت 0.4 فشرده می‌شود.
  • محاسبه‌ی velocity با میانگین متحرک نمایی روی نمونه‌های حرکت.

2. تصمیم رها کردن (touchend)

  • commit به بعدی/قبلی اگر: مسافت > 30% ارتفاع یا |velocity| > 0.55 px/ms (flick).
  • وگرنه spring-back با انیمیشن cubic-bezier(0.22,1,0.36,1) ~340ms.
  • هنگام commit: همان callback های فعلی (onQuestionExit, onQuestionTransition) + setActiveIndex فراخوانی می‌شود؛ انیمیشن inline ادامه پیدا می‌کند و بعد از پایان، style های inline پاک می‌شوند تا state کلاسی بدون پرش تحویل داده شود.

3. قابل مقطوع‌سازی

  • اگر وسط انیمیشن snap دوباره انگشت بگذارد: موقعیت فعلی با getComputedStyle + DOMMatrix خوانده و فریز می‌شود و درگ از همان نقطه ادامه می‌یابد (مثل ریلز).

4. حذف پیش‌نمایش‌های ۱۱۰px (peek)

  • برای اسلاید پنل کامل ریلز-مانند، پنل‌های قبل/بعد در حالت سکون کاملاً خارج از دید (translate-y-full / -translate-y-full) قرار می‌گیرند و wrapper های max-h-[110px] overflow-hidden حذف می‌شوند. خودِ درگ جای affinity بصری را می‌گیرد.
  • wheel دسکتاپ سرجایش می‌ماند و حالا به‌صورت اسلاید کامل انیمیت می‌شود (transition کلاس موجود).

5. حفظ تمام رفتارهای فعلی

حفاظ dropdown-open (شیت باز = بدون درگ)، فوکوس خودکار input سوال فعال، init روی اولین سوال بی‌پاسخ، alignTop، اسپیسر 20%، inert/aria، touchcancel → برگشت، چند-لمسی → نادیده.

خارج از scope

  • تغییر رفتار wheel/کیبورد دسکتاپ، مرور‌سازی horizontal، تغییر auto-focus.
  • شیت کد کشور phone (همان 68svh) — طبق خواسته فقط QuestionSheet تغییر کرد.

راستی‌آزمایی

  • npx vitest run + npx tsc --noEmit (یا biome).
  • تست دستی در مرورگر با viewport موبایل: درگ با ماوس (شبیه‌سازی touch)، wheel، اسکرین‌شات قبل/بعد رها کردن، بررسی مرز rubber-band در اولین/آخرین سوال، باز کردن شیت nationality (تغییر 82svh قبلی) و فوکوس input متنی (حرکت به بالا با کیبورد).