2026-02-05 19:48:36 +00:00
|
|
|
import { Button } from '../button';
|
|
|
|
|
import { AlertTriangle, RefreshCw } from 'lucide-react';
|
|
|
|
|
|
|
|
|
|
export interface LazyErrorFallbackProps {
|
|
|
|
|
pageName: string;
|
|
|
|
|
error?: Error;
|
|
|
|
|
onRetry?: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getErrorMessage(error: Error | undefined): string {
|
|
|
|
|
try {
|
|
|
|
|
if (!error)
|
|
|
|
|
return 'Currently unable to access this component. Please check your connection.';
|
|
|
|
|
if (typeof error === 'string') return error;
|
|
|
|
|
if (error instanceof Error) return error.message;
|
|
|
|
|
return String(error);
|
|
|
|
|
} catch {
|
|
|
|
|
return 'An unknown error occurred.';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function LazyErrorFallback({
|
|
|
|
|
pageName,
|
|
|
|
|
error,
|
|
|
|
|
onRetry,
|
|
|
|
|
}: LazyErrorFallbackProps) {
|
|
|
|
|
return (
|
2026-02-12 01:09:29 +00:00
|
|
|
<div className="flex flex-col items-center justify-center min-h-layout-page-sm p-8 text-center animate-in fade-in zoom-in duration-[var(--sumi-duration-normal)]">
|
refactor: Phase 3a — Global color class migration to SUMI semantics
- Replace all kodo-* color classes across ~100 TSX files:
kodo-void → background, kodo-ink → card, kodo-graphite → muted,
kodo-steel → muted-foreground, kodo-cyan → primary, kodo-magenta → destructive,
kodo-lime → success, kodo-red → destructive, kodo-gold → warning
- Replace cyan-500, magenta-500, lime-500 default Tailwind colors with
semantic equivalents (primary, destructive, success)
- Fix WaveformVisualizer hardcoded hex colors to SUMI values
- Delete global-effects.css (conflicting, redundant with index.css)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 00:51:49 +00:00
|
|
|
<div className="bg-card/50 border border-border/30 rounded-xl p-8 max-w-md w-full shadow-lg backdrop-blur-sm">
|
|
|
|
|
<div className="w-16 h-16 bg-destructive/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
2026-02-08 23:14:40 +00:00
|
|
|
<AlertTriangle className="h-8 w-8 text-destructive" />
|
2026-02-05 19:48:36 +00:00
|
|
|
</div>
|
|
|
|
|
<h2 className="text-xl font-bold mb-2">Failed to load {pageName}</h2>
|
2026-02-08 23:04:51 +00:00
|
|
|
<p className="text-muted-foreground mb-6 text-sm">
|
2026-02-05 19:48:36 +00:00
|
|
|
{getErrorMessage(error)}
|
|
|
|
|
</p>
|
|
|
|
|
<div className="flex flex-col gap-3">
|
|
|
|
|
{onRetry && (
|
|
|
|
|
<Button
|
|
|
|
|
onClick={onRetry}
|
|
|
|
|
variant="outline"
|
|
|
|
|
className="w-full flex items-center justify-center gap-2"
|
|
|
|
|
>
|
|
|
|
|
<RefreshCw className="h-4 w-4" />
|
|
|
|
|
Try Again
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
|
|
|
|
<Button
|
|
|
|
|
onClick={() => window.location.reload()}
|
|
|
|
|
variant="default"
|
|
|
|
|
className="w-full flex items-center justify-center gap-2"
|
|
|
|
|
>
|
|
|
|
|
Refresh Page
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|