From 76c1e2df60171107086c2e7fcdb77d8a9b0a27fd Mon Sep 17 00:00:00 2001 From: rouggy Date: Sun, 28 Jun 2026 19:12:55 +0200 Subject: [PATCH] fix: forcing 3 sec for each notification instead of one replacing the other --- frontend/src/App.tsx | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f632dbc..fbba91d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -490,11 +490,25 @@ export default function App() { }; // Transient success toast (bottom-right, auto-dismiss). Used for things // like "spot sent" where a blocking error banner would be overkill. + // Toasts are QUEUED so two firing at once don't clobber each other: each shows + // for 3s, then the next takes over (no gap). `toast` is the one on screen now. const [toast, setToast] = useState(''); - const showToast = useCallback((msg: string) => { - setToast(msg); - window.setTimeout(() => setToast((t) => (t === msg ? '' : t)), 3500); + const toastQueue = useRef([]); + const toastTimer = useRef(undefined); + const advanceToast = useCallback(() => { + const next = toastQueue.current.shift(); + if (next === undefined) { toastTimer.current = undefined; setToast(''); return; } + setToast(next); + toastTimer.current = window.setTimeout(advanceToast, 3000); }, []); + const showToast = useCallback((msg: string) => { + toastQueue.current.push(msg); + if (toastTimer.current === undefined) advanceToast(); // nothing showing → start now + }, [advanceToast]); + const dismissToast = useCallback(() => { + if (toastTimer.current !== undefined) { window.clearTimeout(toastTimer.current); toastTimer.current = undefined; } + advanceToast(); // skip to the next queued toast (or clear if none) + }, [advanceToast]); // Error banners auto-dismiss after a few seconds (longer than toasts since // they may be multi-line). The X button still closes them immediately. useEffect(() => { @@ -2878,7 +2892,7 @@ export default function App() {
{toast} - +
)}