Spaces:
Sleeping
Sleeping
| import React, { useEffect, useState } from 'react'; | |
| import { createPortal } from 'react-dom'; | |
| import { FaCheckCircle, FaTimesCircle, FaInfoCircle, FaPodcast, FaMusic } from 'react-icons/fa'; | |
| import './WorkflowToast.css'; | |
| // The actual Toast component | |
| const Toast = ({ message, type = 'success', onClose }) => { | |
| const [visible, setVisible] = useState(false); | |
| useEffect(() => { | |
| // Add class to body to prevent scrollbar | |
| document.body.classList.add('has-toast'); | |
| // Show toast immediately | |
| setVisible(true); | |
| // Hide toast after delay | |
| const timer = setTimeout(() => { | |
| setVisible(false); | |
| // Delay actual removal from DOM to allow exit animation to complete | |
| setTimeout(() => { | |
| document.body.classList.remove('has-toast'); | |
| onClose(); | |
| }, 300); | |
| }, 5000); // Extended duration for toast visibility | |
| return () => { | |
| clearTimeout(timer); | |
| document.body.classList.remove('has-toast'); | |
| }; | |
| }, [onClose, message]); | |
| const getIcon = () => { | |
| // Check if message is related to podcast generation | |
| const isPodcastMessage = message.toLowerCase().includes('podcast') || | |
| message.toLowerCase().includes('play') || | |
| message.toLowerCase().includes('listen'); | |
| switch (type) { | |
| case 'success': | |
| return isPodcastMessage ? <FaPodcast /> : <FaCheckCircle />; | |
| case 'error': | |
| return <FaTimesCircle />; | |
| case 'info': | |
| return <FaInfoCircle />; | |
| case 'podcast': | |
| return <FaMusic />; | |
| default: | |
| return <FaCheckCircle />; | |
| } | |
| }; | |
| // Determine if this is a podcast-related toast for special styling | |
| const isPodcastToast = message.toLowerCase().includes('podcast') || type === 'podcast'; | |
| const toastClass = `workflow-toast ${type} ${isPodcastToast ? 'podcast-toast' : ''} ${visible ? 'visible' : ''}`; | |
| return ( | |
| <div className={toastClass}> | |
| <div className="workflow-toast-icon"> | |
| {getIcon()} | |
| </div> | |
| <div className="workflow-toast-message">{message}</div> | |
| </div> | |
| ); | |
| }; | |
| // Portal component to mount toasts in the toast container | |
| const WorkflowToast = (props) => { | |
| const container = document.getElementById('toast-container'); | |
| if (!container) { | |
| // Fallback if the toast container doesn't exist | |
| return <Toast {...props} />; | |
| } | |
| return createPortal(<Toast {...props} />, container); | |
| }; | |
| export default WorkflowToast; |