/** * React error boundary component. * * Catches render-time exceptions in child components and shows a fallback UI. * This is the base component; use PageErrorBoundary or SectionErrorBoundary * for page and section-level boundaries. * * All errors are logged using the telemetry service with structured context * for distributed tracing and debugging. */ import React from "react"; import { Button, makeStyles, Text, tokens } from "@fluentui/react-components"; import { recordCritical } from "../utils/telemetry"; interface ErrorBoundaryState { hasError: boolean; errorMessage: string | null; } interface ErrorBoundaryProps { children: React.ReactNode; title?: string; message?: string; showReloadButton?: boolean; isFullPage?: boolean; onError?: (error: Error, errorInfo: React.ErrorInfo) => void; } interface ErrorBoundaryFallbackProps { title: string; message: string; showReloadButton: boolean; isFullPage: boolean; onReload: () => void; } const useFullPageStyles = makeStyles({ root: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", minHeight: "100vh", padding: tokens.spacingVerticalL, textAlign: "center", gap: tokens.spacingVerticalM, }, message: { maxWidth: "40rem", }, }); const useSectionStyles = makeStyles({ root: { display: "flex", flexDirection: "column", alignItems: "flex-start", padding: tokens.spacingVerticalM, backgroundColor: tokens.colorNeutralBackground3, borderRadius: tokens.borderRadiusMedium, border: `1px solid ${tokens.colorStatusWarningForeground1}`, gap: tokens.spacingVerticalM, }, message: { color: tokens.colorNeutralForeground1, }, }); function ErrorBoundaryFallback({ title, message, showReloadButton, isFullPage, onReload, }: ErrorBoundaryFallbackProps): React.ReactElement { const fullPageStyles = useFullPageStyles(); const sectionStyles = useSectionStyles(); const styles = isFullPage ? fullPageStyles : sectionStyles; return (