import { useState } from "react"; import { Alert, AlertDescription, AlertTitle } from "@godxjp/ui/feedback"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display"; import { FormField, Input, PasswordInput, PasswordStrength } from "@godxjp/ui/data-entry"; import { Button, Logo, Text } from "@godxjp/ui/general"; import { AuthFooter, AuthShell, AuthStack, Flex } from "@godxjp/ui/layout"; import { AppSettingPicker } from "@godxjp/ui/navigation"; /** * PASSWORD RECOVERY — the four canonical SCR-008 panel states, stacked at the real 432px measure. * * All four are the SAME anatomy; only the notice, the fields and the copy change: * Card > CardHeader(CardTitle + CardDescription) > CardContent > AuthStack * [notice Alert] → [fields] → [Button fullWidth] → [fallback row] * * A real route renders ONE of these panels with `CardTitle level={1}`. This standalone comparison * keeps that contract on the first panel, then uses `level={2}` for the remaining state sections, * so the frame has exactly one meaningful page heading and every state keeps a valid outline. * * State coverage: request (idle) · sent (success notice + DISABLED resend during cooldown) · * new-password (field ERROR + strength meter) · expired (destructive notice). The LOADING state is * covered by the MFA example. Every panel's primary action spans the panel; every fallback row is * `Flex justify="between" wrap`, so it collapses to a stack when the labels stop fitting. */ export default function Demo() { const [email, setEmail] = useState("hanako@example.co.jp"); const [password, setPassword] = useState("Godx-2026"); const [confirmation, setConfirmation] = useState("Godx-202"); const maskedEmail = "h*****@example.co.jp"; return ( GoDX ID } footer={ } /> } > 1 / 4 · request · リセットリンクの発行を依頼する パスワードをリセット 登録済みのメールアドレスにリセットリンクをお送りします。 setEmail(event.target.value)} /> 2 / 4 · sent · 送信済み(成功通知 + 再送クールダウン中は disabled) メールを確認してください リセットリンクを送信しました。リンクの有効期限は 30 分です。 {maskedEmail} に送信しました メールが届かない場合は、迷惑メールフォルダもご確認ください。 3 / 4 · new-password · 新しいパスワードの設定(確認欄の不一致エラー) 新しいパスワードを設定 他のサービスで使用していないパスワードを設定してください。 setPassword(event.target.value)} /> setConfirmation(event.target.value)} /> 4 / 4 · expired · リンクの有効期限切れ(destructive 通知) リンクの有効期限が切れています セキュリティのため、リセットリンクは発行から 30 分で失効します。 このリンクは使用できません 期限切れ、または既に使用されたリンクです。新しいリンクを発行してください。 ); }