LoadingState appears only after 300ms: fast API answers no longer flash the loader (packs screen and every other data screen)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 17:05:52 +03:30
parent ec1bfc721d
commit b11016c6ea
2 changed files with 15 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
import type { ButtonHTMLAttributes, CSSProperties, ReactNode } from 'react';
import { useEffect, useState, type ButtonHTMLAttributes, type CSSProperties, type ReactNode } from 'react';
import { ChevronRight, RotateCw } from 'lucide-react';
import { SeyarMascot } from '@/mascots/SeyarMascot';
import type { SeyarChar, SeyarMood } from '@/mascots/seyar';
@@ -130,8 +130,19 @@ function StateBox({ char, mood, text, children }: { char: SeyarChar; mood: Seyar
);
}
export function LoadingState({ text = 'یه لحظه صبر کن…', char = 'sigma' as SeyarChar }) {
return <StateBox char={char} mood="idle" text={text} />;
/**
* لودر فقط بعد از `delayMs` دیده می‌شود. پاسخِ API معمولاً زیرِ ۳۰۰ms می‌رسد و نشان دادنِ لودر برای
* همان چند فریم، پرشِ ریزِ «لودر ← محتوا» می‌ساخت؛ حالا تا آن لحظه جای خالی می‌ماند. اگر پاسخ
* کند باشد کاربر باز هم لودر را می‌بیند. در مرورگر با شبکه‌ی کند آزموده نشده.
*/
export function LoadingState({ text = 'یه لحظه صبر کن…', char = 'sigma' as SeyarChar, delayMs = 300 }) {
const [show, setShow] = useState(delayMs <= 0);
useEffect(() => {
if (delayMs <= 0) return;
const t = setTimeout(() => setShow(true), delayMs);
return () => clearTimeout(t);
}, [delayMs]);
return show ? <StateBox char={char} mood="idle" text={text} /> : null;
}
export function ErrorState({ error, onRetry, text }: { error?: unknown; onRetry?: () => void; text?: string }) {