/ src / components / layout / error-fallback.tsx
error-fallback.tsx
 1  'use client'
 2  
 3  type ErrorFallbackProps = {
 4    title?: string
 5    message?: string
 6    primaryLabel?: string
 7    onPrimaryAction?: () => void
 8    secondaryLabel?: string
 9    onSecondaryAction?: () => void
10  }
11  
12  export function ErrorFallback({
13    title = 'Something went wrong',
14    message = 'An unexpected error occurred. Try again or reload the page.',
15    primaryLabel = 'Reload',
16    onPrimaryAction,
17    secondaryLabel,
18    onSecondaryAction,
19  }: ErrorFallbackProps) {
20    return (
21      <div className="flex min-h-[50vh] flex-1 flex-col items-center justify-center bg-bg px-8">
22        <div className="max-w-[420px] text-center">
23          <div className="mx-auto mb-5 flex h-14 w-14 items-center justify-center rounded-[16px] border border-red-500/20 bg-red-500/10">
24            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" className="text-red-400">
25              <circle cx="12" cy="12" r="10" />
26              <line x1="12" y1="8" x2="12" y2="12" />
27              <line x1="12" y1="16" x2="12.01" y2="16" />
28            </svg>
29          </div>
30          <h2 className="mb-2 font-display text-[22px] font-700 tracking-[-0.02em] text-text">
31            {title}
32          </h2>
33          <p className="mb-6 text-[14px] text-text-3">
34            {message}
35          </p>
36          <div className="flex flex-wrap items-center justify-center gap-3">
37            <button
38              onClick={onPrimaryAction}
39              className="inline-flex cursor-pointer items-center gap-2 rounded-[12px] border-none bg-accent-bright px-6 py-3 text-[14px] font-600 text-white shadow-[0_4px_16px_rgba(99,102,241,0.2)] transition-all hover:brightness-110 active:scale-[0.97]"
40              style={{ fontFamily: 'inherit' }}
41            >
42              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
43                <polyline points="23 4 23 10 17 10" />
44                <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
45              </svg>
46              {primaryLabel}
47            </button>
48            {secondaryLabel && onSecondaryAction ? (
49              <button
50                onClick={onSecondaryAction}
51                className="inline-flex cursor-pointer items-center rounded-[12px] border border-border bg-transparent px-5 py-3 text-[14px] font-600 text-text transition-colors hover:bg-panel/60"
52                style={{ fontFamily: 'inherit' }}
53              >
54                {secondaryLabel}
55              </button>
56            ) : null}
57          </div>
58        </div>
59      </div>
60    )
61  }