import React, { Suspense, useEffect } from "react"; import Login from "../../app/components/modals/Login"; import LoginForm from "../../app/components/modals/Login/LoginForm"; /** * Storybook runs outside Next.js request context; successful "Send link" needs fetch mocked * because `requestMagicLink` POSTs to `/api/auth/magic-link/request`. */ function MagicLinkFetchMock({ children }: { children: React.ReactNode }) { useEffect(() => { const orig = globalThis.fetch; globalThis.fetch = async ( input: RequestInfo | URL, init?: RequestInit, ): Promise => { const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url; if (url.includes("/api/auth/magic-link/request")) { return new Response("{}", { status: 200, headers: { "Content-Type": "application/json" }, }); } return orig(input as Request, init); }; return () => { globalThis.fetch = orig; }; }, []); return <>{children}; } export default { title: "Components/Modals/Login", component: Login, parameters: { layout: "fullscreen", nextjs: { appDirectory: true, navigation: { pathname: "/login", }, }, docs: { description: { component: "Full-page style login shell (yellow backdrop) with modal card. Uses magic-link `LoginForm` inside. Matches `/login` and header modal usage.", }, }, }, decorators: [ (Story: () => React.ReactNode) => (
), ], tags: ["autodocs"], }; export const ModalChromeOnly = { name: "Modal (placeholder content)", render: () => ( {}} ariaLabelledBy="login-modal-heading" belowCard={ ← Back to home } >

Placeholder body — use "With magic link form" for the real flow.

), }; export const WithMagicLinkForm = { name: "With magic link form", render: () => ( {}} ariaLabelledBy="login-modal-heading" belowCard={ ← Back to home } > Loading…

}>
), }; export const FormOnly = { name: "Login form (card inset)", parameters: { docs: { description: { story: "Form only, for inspecting copy and layout without the modal chrome. Wrap in `Login` in the app.", }, }, }, render: () => (
Loading…

}>
), };