{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sign-in-flow",
  "type": "registry:ui",
  "title": "Sign-in flow",
  "description": "Coordinates identity input, pending, error, and success while retaining entered context.",
  "dependencies": [
    "motion"
  ],
  "categories": [
    "forms-input"
  ],
  "docs": "https://motion-lexicon.pages.dev/en/components/sign-in-flow/",
  "meta": {
    "engines": [
      "motion"
    ],
    "runtimeCost": "light",
    "signature": "Sign-in card keeps one geometry through states",
    "sceneFamily": "product-mono",
    "motionRole": "ui",
    "primaryState": "Complete email and password sign-in card",
    "assetProvenance": "self-contained"
  },
  "files": [
    {
      "path": "src/registry/components/sign-in-flow.tsx",
      "type": "registry:ui",
      "target": "components/motion-lexicon/sign-in-flow.tsx",
      "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\n\nexport type SignInValues = { email: string; password: string };\nexport type SignInFlowProps = { title?: string; onSubmit?: (values: SignInValues) => void | Promise<void>; className?: string };\n\nexport function SignInFlow({ title = \"Welcome back\", onSubmit, className = \"\" }: SignInFlowProps) {\n  const reduced = useReducedMotion() === true; const id = useId(); const [email, setEmail] = useState(\"\"); const [password, setPassword] = useState(\"\"); const [status, setStatus] = useState<\"idle\" | \"pending\" | \"error\" | \"success\">(\"idle\"); const [error, setError] = useState(\"\");\n  const submit = async () => { if (!email.includes(\"@\") || password.length < 4) { setStatus(\"error\"); setError(\"Enter a valid email and password.\"); return; } try { setStatus(\"pending\"); setError(\"\"); await onSubmit?.({ email, password }); setStatus(\"success\"); } catch { setStatus(\"error\"); setError(\"Sign in could not be completed. Try again.\"); } };\n  return <form onSubmit={(event) => { event.preventDefault(); void submit(); }} className={`rounded-[18px] bg-[#1f2322] p-5 text-white shadow-[0_18px_46px_-28px_rgba(12,16,15,.82)] ${className}`}><span className=\"font-mono text-[10px] uppercase tracking-[.18em] text-[#a5c5a9]\">Member access</span><h3 id={`${id}-title`} className=\"mt-4 text-3xl font-medium tracking-[-.05em]\">{title}</h3><div className=\"mt-6 space-y-3\"><label className=\"block text-[11px] text-white/65\" htmlFor={`${id}-email`}>Email<input id={`${id}-email`} value={email} onChange={(event) => { setEmail(event.target.value); setStatus(\"idle\"); }} type=\"email\" autoComplete=\"email\" className=\"mt-1.5 min-h-11 w-full rounded-lg border border-white/15 bg-white/[.06] px-3 text-[13px] text-white outline-none placeholder:text-white/32 focus-visible:ring-2 focus-visible:ring-[#9ed2a5]\" placeholder=\"you@example.com\" /></label><label className=\"block text-[11px] text-white/65\" htmlFor={`${id}-password`}>Password<input id={`${id}-password`} value={password} onChange={(event) => { setPassword(event.target.value); setStatus(\"idle\"); }} type=\"password\" autoComplete=\"current-password\" className=\"mt-1.5 min-h-11 w-full rounded-lg border border-white/15 bg-white/[.06] px-3 text-[13px] text-white outline-none focus-visible:ring-2 focus-visible:ring-[#9ed2a5]\" /></label></div><button type=\"submit\" disabled={status === \"pending\"} className=\"mt-5 min-h-11 w-full rounded-full bg-[#d9ebc8] px-4 text-[12px] font-medium text-[#243124] outline-none transition hover:bg-[#ecf6e3] disabled:opacity-60 focus-visible:ring-2 focus-visible:ring-white\">{status === \"pending\" ? \"Signing in…\" : status === \"success\" ? \"You’re in\" : \"Sign in\"}</button><AnimatePresence>{status === \"error\" ? <motion.p role=\"alert\" initial={reduced ? false : { opacity: 0, y: -5 }} animate={{ opacity: 1, y: 0 }} className=\"mt-3 text-[12px] text-[#ffb5a9]\">{error}</motion.p> : null}</AnimatePresence></form>;\n}\n"
    }
  ]
}
