From e45e742850716ba9889a01acf23fa0be4130fc62 Mon Sep 17 00:00:00 2001 From: Alex Bueno <44420072+aweell@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:55:06 +0100 Subject: [PATCH] Fix toast issues --- .../components/toast-wrapper.jsx | 37 +++++++---- .../advent-calendar-2024/components/toast.jsx | 63 ++++++++++++------- .../components/toast.module.css | 23 +++++++ 3 files changed, 87 insertions(+), 36 deletions(-) create mode 100644 src/pages/advent-calendar-2024/components/toast.module.css diff --git a/src/pages/advent-calendar-2024/components/toast-wrapper.jsx b/src/pages/advent-calendar-2024/components/toast-wrapper.jsx index 7e5935bd6a..f9c502e355 100644 --- a/src/pages/advent-calendar-2024/components/toast-wrapper.jsx +++ b/src/pages/advent-calendar-2024/components/toast-wrapper.jsx @@ -1,7 +1,10 @@ import { useState, useEffect } from "react"; import Toast from "./toast"; // Assuming your Toast component is already implemented +import { Stack } from "@telefonica/mistica"; const ToastWrapper = ({ toasts, removeToast }) => { + const totalToasts = toasts.length; + return (
{ right: "16px", }} > -
- {toasts.map((toast, index) => ( - removeToast(toast.id)} // Dismiss the toast by `id` - /> - ))} -
+ + {toasts.map((toast, index) => { + const scaleValue = 1 - index * 0.2; + console.log(`scale(${scaleValue})`); // Log the scale value + + return ( + removeToast(toast.id)} // Dismiss the toast by `id` + style={{ + right: "16px", + zIndex: 1000 + index, + }} + delay={(totalToasts - index - 1) * 1000} // Last toast will have the longest delay + /> + ); + })} +
); }; diff --git a/src/pages/advent-calendar-2024/components/toast.jsx b/src/pages/advent-calendar-2024/components/toast.jsx index 0c1353ba87..69b2d96722 100644 --- a/src/pages/advent-calendar-2024/components/toast.jsx +++ b/src/pages/advent-calendar-2024/components/toast.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState, useRef } from "react"; +import { useState, useEffect, useRef } from "react"; import { Stack, Text3, @@ -9,16 +9,19 @@ import { IconButton, IconCloseRegular, } from "@telefonica/mistica"; +import styles from "./toast.module.css"; const Toast = ({ title, description, icon: Icon, duration = 3000, - style, + delay = 0, onClose, + style, }) => { - const [visible, setVisible] = useState(true); + const [visible, setVisible] = useState(true); // Initial visibility is true + const [fadeOut, setFadeOut] = useState(false); // Controls fade-out animation const [isHovered, setIsHovered] = useState(false); const timeoutRef = useRef(null); @@ -32,44 +35,53 @@ const Toast = ({ const startHideTimeout = () => { clearHideTimeout(); timeoutRef.current = setTimeout(() => { - setVisible(false); // This will trigger unmount if necessary - onClose?.(); // Pass the ID to remove the toast + setFadeOut(true); // Trigger fade-out before setting visible to false + onClose?.(); // Trigger onClose callback to remove toast }, duration); }; + // Handle visibility change when hovered or not useEffect(() => { - if (!isHovered) { - startHideTimeout(); // Start timeout when not hovered - } else { - clearHideTimeout(); // Clear timeout when hovered - } + const handleTimeout = () => { + if (!isHovered) { + setTimeout(startHideTimeout, delay); // Delay before auto-dismissing + } else { + clearHideTimeout(); // Clear timeout when hovered + } + }; + + handleTimeout(); return () => clearHideTimeout(); // Cleanup timeout on unmount - }, [isHovered, duration]); + }, [isHovered, delay, duration]); - // Always render dismiss button, regardless of toast visibility - const handleDismiss = () => { - setVisible(false); - clearHideTimeout(); - onClose?.(); // Ensure it triggers onClose from parent - }; + useEffect(() => { + if (fadeOut) { + // Wait for the exit animation to complete before removing the toast + timeoutRef.current = setTimeout(() => { + setVisible(false); // Remove from the DOM after animation + }, 500); // Match the duration of your fade-out transition + } + + return () => clearTimeout(timeoutRef.current); // Cleanup the fade-out timeout + }, [fadeOut]); - if (!visible) return null; // Hide toast when not visible + if (!visible) return null; // If not visible, do not render the toast return (
setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} + onMouseEnter={() => setIsHovered(true)} // Trigger hover state + onMouseLeave={() => setIsHovered(false)} // Reset hover state >
- {/* Dismiss button should always be on top */}
{ + setFadeOut(true); // Trigger fade-out animation on close + clearHideTimeout(); // Clear the timeout when manually closed + onClose?.(); // Trigger onClose callback to remove toast + }} />
diff --git a/src/pages/advent-calendar-2024/components/toast.module.css b/src/pages/advent-calendar-2024/components/toast.module.css new file mode 100644 index 0000000000..1e0746c125 --- /dev/null +++ b/src/pages/advent-calendar-2024/components/toast.module.css @@ -0,0 +1,23 @@ +/* toast.module.css */ + +/* Keyframes for the toast entry animation */ +@keyframes slideIn { + 0% { + opacity: 0; + transform: translateY(400px); /* Start below */ + } + 100% { + opacity: 1; /* Fade in */ + transform: translateY(0); /* Move to final position */ + } +} + + + +/* Base toast styles */ +.toast { + opacity: 0; + transform: translateY(400px); /* Initial off-screen position */ + animation: slideIn 0.5s ease-out forwards; /* Entry animation */ +} +