Dynamic imports for heavy components (Kanban, Gantt, CommandPalette), skip-to-content link, ARIA landmarks/labels on sidebar, breadcrumbs, topbar notifications, kanban board, gantt timeline, and pipeline progress. Focus-visible ring styles for keyboard navigation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import { AlertTriangle, RefreshCw } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
export default function GlobalError({
|
|
error,
|
|
reset,
|
|
}: {
|
|
error: Error & { digest?: string };
|
|
reset: () => void;
|
|
}) {
|
|
useEffect(() => {
|
|
console.error("Global error:", error);
|
|
}, [error]);
|
|
|
|
return (
|
|
<div className="flex min-h-screen items-center justify-center p-6" role="alert">
|
|
<div className="max-w-md text-center">
|
|
<AlertTriangle className="mx-auto mb-4 h-12 w-12 text-[var(--accent)]" aria-hidden="true" />
|
|
<h1 className="font-heading text-2xl font-bold">
|
|
Something went wrong
|
|
</h1>
|
|
<p className="mt-2 text-sm text-[var(--muted-foreground)]">
|
|
{error.message || "An unexpected error occurred."}
|
|
</p>
|
|
{error.digest && (
|
|
<p className="mt-1 font-mono text-xs text-[var(--muted-foreground)]">
|
|
Error ID: {error.digest}
|
|
</p>
|
|
)}
|
|
<Button onClick={reset} className="mt-6">
|
|
<RefreshCw className="mr-2 h-4 w-4" />
|
|
Try Again
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|