canvas-website/src/components/NotificationsDisplay.tsx

105 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from 'react';
import { useNotifications, Notification } from '../context/NotificationContext';
/**
* Component to display a single notification
*/
const NotificationItem: React.FC<{
notification: Notification;
onClose: (id: string) => void;
}> = ({ notification, onClose }) => {
const [isExiting, setIsExiting] = useState(false);
const exitDuration = 300; // ms for exit animation
// Set up automatic dismissal based on notification timeout
useEffect(() => {
if (notification.timeout > 0) {
const timer = setTimeout(() => {
setIsExiting(true);
// Wait for exit animation before removing
setTimeout(() => {
onClose(notification.id);
}, exitDuration);
}, notification.timeout);
return () => clearTimeout(timer);
}
}, [notification, onClose]);
// Handle manual close
const handleClose = () => {
setIsExiting(true);
// Wait for exit animation before removing
setTimeout(() => {
onClose(notification.id);
}, exitDuration);
};
// Determine icon based on notification type
const getIcon = () => {
switch (notification.type) {
case 'success':
return '✓';
case 'error':
return '✕';
case 'warning':
return '⚠';
case 'info':
default:
return '';
}
};
return (
<div
className={`notification ${notification.type} ${isExiting ? 'exiting' : ''}`}
style={{
animationDuration: `${exitDuration}ms`,
}}
>
<div className="notification-icon">
{getIcon()}
</div>
<div className="notification-content">
{notification.msg}
</div>
<button
className="notification-close"
onClick={handleClose}
aria-label="Close notification"
>
×
</button>
</div>
);
};
/**
* Component that displays all active notifications
*/
const NotificationsDisplay: React.FC = () => {
const { notifications, removeNotification } = useNotifications();
// Don't render anything if there are no notifications
if (notifications.length === 0) {
return null;
}
return (
<div className="notifications-container">
{notifications.map((notification) => (
<NotificationItem
key={notification.id}
notification={notification}
onClose={removeNotification}
/>
))}
</div>
);
};
export default NotificationsDisplay;