/** * Notification display container. * * Renders all active notifications from the NotificationService as a vertical stack * at the top of the application. Each notification displays with appropriate styling * based on its intent level and auto-dismisses after a configured duration. */ import { MessageBar, MessageBarBody, makeStyles, tokens } from "@fluentui/react-components"; import { useNotificationQueue } from "../services/notificationService"; import type { Notification } from "../types/notification"; /** Styles for the notification container and messages. */ const useStyles = makeStyles({ container: { position: "fixed", top: 0, left: 0, right: 0, zIndex: 10000, // Above all other content pointerEvents: "none", // Allow clicks to pass through to content below padding: tokens.spacingVerticalL, maxHeight: "60vh", overflowY: "auto", }, stack: { display: "flex", flexDirection: "column", gap: tokens.spacingVerticalM, maxWidth: "600px", margin: "0 auto", }, messageBar: { pointerEvents: "auto", // But restore pointer events on the messages }, }); /** * NotificationContainer renders the notification queue. * * Place this component once in your app root (e.g., in App.tsx) to display * all notifications managed by the NotificationService. * * @returns JSX element rendering the notification stack or empty fragment if no notifications. */ export function NotificationContainer(): React.JSX.Element { const styles = useStyles(); const notifications = useNotificationQueue(); if (notifications.length === 0) { return <>; } return (
{notifications.map((notification) => ( ))}
); } /** * Single notification message component. * Renders a Fluent UI MessageBar with appropriate styling based on notification intent. */ interface NotificationMessageProps { notification: Notification; } function NotificationMessage({ notification }: NotificationMessageProps): React.JSX.Element { const styles = useStyles(); // Map notification intent to MessageBar intent const messageBarIntent: "success" | "error" | "warning" | "info" = notification.intent === "info" ? "info" : notification.intent; return ( {notification.message} ); }