import React, { useEffect, useState } from "react"; import { Alert, Box, Button, CircularProgress, Typography } from "@mui/material"; import { visuallyHidden } from "@mui/utils"; import type { ViewResourceError } from "../hooks/useViewResource"; import { useI18n } from "../i18n/I18nProvider"; type Props = { loading?: boolean; error?: ViewResourceError | null; title: string; description?: string; retryLabel?: string; onRetry?: () => void | Promise; compact?: boolean; }; export default function ViewStateNotice({ loading = false, error = null, title, description, retryLabel, onRetry, compact = false }: Props) { const { t } = useI18n(); const resolvedRetryLabel = retryLabel ?? t("retry"); const [observedLoading, setObservedLoading] = useState(loading); useEffect(() => { if (loading) setObservedLoading(true); }, [loading]); // Keep one live region mounted through the read. An idle/error-only consumer // has not completed a load; unrelated form edits must not announce anything. const status = {loading ? t("loading") : !error && observedLoading ? t("contentLoaded") : ""} ; if (loading) { return ( <>{status} ); } if (!error) return <>{status}; const severity = error.kind === "unauthorized" ? "warning" : error.kind === "unavailable" ? "error" : "error"; const detail = error.message !== title && error.message !== description ? error.message : null; return ( <>{status} void onRetry()}>{resolvedRetryLabel} : undefined} > {title} {description ? {description} : null} {detail ? {detail} : null} ); }