diff --git a/src/components/toast/ToastContainer.tsx b/src/components/toast/ToastContainer.tsx
index 756879d..e0143e6 100644
--- a/src/components/toast/ToastContainer.tsx
+++ b/src/components/toast/ToastContainer.tsx
@@ -1,4 +1,5 @@
import { AnimatePresence, motion } from "framer-motion";
+import { X } from "lucide-react";
import { springs } from "@/lib/motion";
import { useToastStore } from "@/stores/toast-store";
@@ -10,9 +11,17 @@ const TYPE_STYLES = {
export function ToastContainer() {
const toasts = useToastStore((s) => s.toasts);
+ const removeToast = useToastStore((s) => s.removeToast);
+ const pauseToast = useToastStore((s) => s.pauseToast);
+ const resumeToast = useToastStore((s) => s.resumeToast);
return (
-
+
{toasts.map((toast) => (
pauseToast(toast.id)}
+ onMouseLeave={() => resumeToast(toast.id)}
+ onFocus={() => pauseToast(toast.id)}
+ onBlur={() => resumeToast(toast.id)}
>
- {toast.message}
+ {toast.message}
+
))}
diff --git a/src/stores/toast-store.ts b/src/stores/toast-store.ts
index f918f39..7ecedfa 100644
--- a/src/stores/toast-store.ts
+++ b/src/stores/toast-store.ts
@@ -12,9 +12,28 @@ interface ToastState {
toasts: Toast[];
addToast: (message: string, type?: ToastType) => void;
removeToast: (id: string) => void;
+ pauseToast: (id: string) => void;
+ resumeToast: (id: string) => void;
}
let nextId = 0;
+const timers = new Map
>();
+const remaining = new Map();
+const startTimes = new Map();
+
+const TOAST_DURATION = 8000;
+
+function startTimer(id: string, duration: number, set: (fn: (s: ToastState) => Partial) => void) {
+ startTimes.set(id, Date.now());
+ remaining.set(id, duration);
+ const timer = setTimeout(() => {
+ set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) }));
+ timers.delete(id);
+ remaining.delete(id);
+ startTimes.delete(id);
+ }, duration);
+ timers.set(id, timer);
+}
export const useToastStore = create((set) => ({
toasts: [],
@@ -22,12 +41,33 @@ export const useToastStore = create((set) => ({
addToast: (message, type = "info") => {
const id = String(++nextId);
set((s) => ({ toasts: [...s.toasts, { id, message, type }] }));
- setTimeout(() => {
- set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) }));
- }, 3000);
+ startTimer(id, TOAST_DURATION, set);
},
removeToast: (id) => {
+ const timer = timers.get(id);
+ if (timer) clearTimeout(timer);
+ timers.delete(id);
+ remaining.delete(id);
+ startTimes.delete(id);
set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) }));
},
+
+ pauseToast: (id) => {
+ const timer = timers.get(id);
+ const start = startTimes.get(id);
+ const rem = remaining.get(id);
+ if (timer && start != null && rem != null) {
+ clearTimeout(timer);
+ timers.delete(id);
+ remaining.set(id, rem - (Date.now() - start));
+ }
+ },
+
+ resumeToast: (id) => {
+ const rem = remaining.get(id);
+ if (rem != null && rem > 0) {
+ startTimer(id, rem, set);
+ }
+ },
}));