/** * Reusable page-level feedback components. * * Three shared building blocks for consistent data-loading UI across all pages: * * - {@link PageLoading} — Centred `Spinner` for full-region loading states. * - {@link PageError} — `MessageBar` with an error message and a retry button. * - {@link PageEmpty} — Centred neutral message for zero-result states. */ import { Button, MessageBar, MessageBarActions, MessageBarBody, MessageBarTitle, Spinner, Text, makeStyles, tokens, } from "@fluentui/react-components"; import { ArrowClockwiseRegular } from "@fluentui/react-icons"; // --------------------------------------------------------------------------- // Styles // --------------------------------------------------------------------------- const useStyles = makeStyles({ centred: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", minHeight: "120px", gap: tokens.spacingVerticalM, padding: tokens.spacingVerticalL, }, emptyText: { color: tokens.colorNeutralForeground3, textAlign: "center", }, }); // --------------------------------------------------------------------------- // PageLoading // --------------------------------------------------------------------------- export interface PageLoadingProps { /** Short description shown next to the spinner. */ label?: string; } /** * Full-region loading indicator using a Fluent UI `Spinner`. * * @example * ```tsx * if (loading) return ; * ``` */ export function PageLoading({ label = "Loading…" }: PageLoadingProps): React.JSX.Element { const styles = useStyles(); return (
); } // --------------------------------------------------------------------------- // PageError // --------------------------------------------------------------------------- export interface PageErrorProps { /** Error message shown in the `MessageBar`. */ message: string; /** Optional callback invoked when the user clicks "Retry". */ onRetry?: () => void; } /** * Error state `MessageBar` with an optional retry button. * * @example * ```tsx * if (error) return ; * ``` */ export function PageError({ message, onRetry }: PageErrorProps): React.JSX.Element { return ( Error {message} {onRetry != null && ( )} ); } // --------------------------------------------------------------------------- // PageEmpty // --------------------------------------------------------------------------- export interface PageEmptyProps { /** Message displayed to the user, e.g. "No bans found." */ message: string; } /** * Centred empty-state message for tables or lists with zero results. * * @example * ```tsx * if (items.length === 0) return ; * ``` */ export function PageEmpty({ message }: PageEmptyProps): React.JSX.Element { const styles = useStyles(); return (
{message}
); }