fix: forcing 3 sec for each notification instead of one replacing the other
This commit is contained in:
+18
-4
@@ -490,11 +490,25 @@ export default function App() {
|
|||||||
};
|
};
|
||||||
// Transient success toast (bottom-right, auto-dismiss). Used for things
|
// Transient success toast (bottom-right, auto-dismiss). Used for things
|
||||||
// like "spot sent" where a blocking error banner would be overkill.
|
// 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 [toast, setToast] = useState('');
|
||||||
const showToast = useCallback((msg: string) => {
|
const toastQueue = useRef<string[]>([]);
|
||||||
setToast(msg);
|
const toastTimer = useRef<number | undefined>(undefined);
|
||||||
window.setTimeout(() => setToast((t) => (t === msg ? '' : t)), 3500);
|
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
|
// Error banners auto-dismiss after a few seconds (longer than toasts since
|
||||||
// they may be multi-line). The X button still closes them immediately.
|
// they may be multi-line). The X button still closes them immediately.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -2878,7 +2892,7 @@ export default function App() {
|
|||||||
<div className="flex items-center gap-1.5 rounded-md border border-emerald-300 bg-emerald-50 text-emerald-800 px-2.5 py-1 text-xs shadow min-w-0 animate-in fade-in">
|
<div className="flex items-center gap-1.5 rounded-md border border-emerald-300 bg-emerald-50 text-emerald-800 px-2.5 py-1 text-xs shadow min-w-0 animate-in fade-in">
|
||||||
<Satellite className="size-3.5 shrink-0" />
|
<Satellite className="size-3.5 shrink-0" />
|
||||||
<span className="truncate" title={toast}>{toast}</span>
|
<span className="truncate" title={toast}>{toast}</span>
|
||||||
<button className="shrink-0 text-emerald-600 hover:text-emerald-800" onClick={() => setToast('')}><X className="size-3" /></button>
|
<button className="shrink-0 text-emerald-600 hover:text-emerald-800" onClick={dismissToast}><X className="size-3" /></button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user