import type { Meta, StoryObj } from '@storybook/react'; import React, { useState } from 'react'; import { AppErrorBoundary, PageErrorBoundary, SectionErrorBoundary } from './error-boundary'; // ── Crash helper ───────────────────────────────────────────────────────────── // A component that throws on the next render when `shouldCrash` is true. // Used in every story to demonstrate real boundary behaviour. function Crashable({ shouldCrash, label }: { shouldCrash: boolean; label: string }) { if (shouldCrash) throw new Error(`Simulated crash in: ${label}`); return (

{label} — rendering normally. Click the button to simulate a crash.

); } // ── Wrapper that controls crash state ──────────────────────────────────────── function CrashController({ Boundary, label, }: { Boundary: React.ComponentType<{ children: React.ReactNode }>; label: string; }) { const [crashed, setCrashed] = useState(false); return (
); } // ── Meta ────────────────────────────────────────────────────────────────────── const meta: Meta = { title: 'Shared/ErrorBoundary', parameters: { layout: 'padded', docs: { description: { component: 'Three pre-configured ErrorBoundary variants for root, page, and section-level error isolation. Click "Simulate crash" to see each fallback UI.', }, }, }, }; export default meta; // ── Stories ─────────────────────────────────────────────────────────────────── export const App: StoryObj = { name: 'AppErrorBoundary (root fallback)', render: () => , parameters: { docs: { description: { story: '`AppErrorBoundary` renders a full-screen fallback using only inline styles — no Tailwind dependency — so it works even if the design system itself fails to load.', }, }, }, }; export const Page: StoryObj = { name: 'PageErrorBoundary (route fallback)', render: () => , parameters: { docs: { description: { story: '`PageErrorBoundary` shows a half-height Tailwind-styled fallback. The sidebar, header, and other chrome remain visible — only the page content area is replaced.', }, }, }, }; export const Section: StoryObj = { name: 'SectionErrorBoundary (inline fallback)', render: () => (

Each card below is independently wrapped. Crashing one does not affect the others.

{(['Team table', 'Chart', 'Assistant panel'] as const).map(label => ( ))}
), parameters: { docs: { description: { story: '`SectionErrorBoundary` renders a compact inline fallback. Multiple independent sections on the same page can each fail in isolation.', }, }, }, };