From 66254496fcd787b266128b7af724aad3be6c7c36 Mon Sep 17 00:00:00 2001 From: shrimbly Date: Mon, 12 Jan 2026 12:41:01 +1300 Subject: [PATCH] feat(08-01): update Toast component for error notifications - Move toast position from bottom-center to top-right - Add persistent mode to disable auto-dismiss for errors - Add expandable details section for full error messages - Maintain backward compatibility with existing callers Co-Authored-By: Claude Opus 4.5 --- src/components/Toast.tsx | 67 ++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx index 2fe43470..527e755f 100644 --- a/src/components/Toast.tsx +++ b/src/components/Toast.tsx @@ -1,20 +1,24 @@ "use client"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { create } from "zustand"; interface ToastState { message: string | null; type: "info" | "success" | "warning" | "error"; - show: (message: string, type?: "info" | "success" | "warning" | "error") => void; + persistent: boolean; + details: string | null; + show: (message: string, type?: "info" | "success" | "warning" | "error", persistent?: boolean, details?: string | null) => void; hide: () => void; } export const useToast = create((set) => ({ message: null, type: "info", - show: (message, type = "info") => set({ message, type }), - hide: () => set({ message: null }), + persistent: false, + details: null, + show: (message, type = "info", persistent = false, details = null) => set({ message, type, persistent, details }), + hide: () => set({ message: null, persistent: false, details: null }), })); const typeStyles = { @@ -48,34 +52,59 @@ const typeIcons = { }; export function Toast() { - const { message, type, hide } = useToast(); + const { message, type, persistent, details, hide } = useToast(); + const [isExpanded, setIsExpanded] = useState(false); useEffect(() => { - if (message) { + // Reset expanded state when toast changes + setIsExpanded(false); + }, [message]); + + useEffect(() => { + if (message && !persistent) { const timer = setTimeout(() => { hide(); }, 4000); return () => clearTimeout(timer); } - }, [message, hide]); + }, [message, persistent, hide]); if (!message) return null; return ( -
+
- {typeIcons[type]} - {message} - +
+ {typeIcons[type]} + {message} + +
+ {details && ( + <> + + {isExpanded && ( +
+
+                  {details}
+                
+
+ )} + + )}
);