{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "onboarding-flow",
  "type": "registry:block",
  "title": "Onboarding flow",
  "description": "Organizes account setup, file import, and completion checklist into a successful first-workspace path.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://motion-lexicon.pages.dev/r/drawer.json",
    "https://motion-lexicon.pages.dev/r/file-dropzone.json",
    "https://motion-lexicon.pages.dev/r/multi-step-form.json",
    "https://motion-lexicon.pages.dev/r/onboarding-checklist.json",
    "https://motion-lexicon.pages.dev/r/progress-bar.json",
    "https://motion-lexicon.pages.dev/r/tabs.json"
  ],
  "categories": [
    "page-block"
  ],
  "docs": "https://motion-lexicon.pages.dev/en/blocks/onboarding-flow/",
  "meta": {
    "engines": [
      "motion"
    ],
    "runtimeCost": "medium",
    "signature": "Form, import, and checklist completion progress continuously toward the first successful state.",
    "sceneFamily": "product-mono",
    "primaryState": "In-progress account setup and import steps",
    "componentIds": [
      "drawer",
      "file-dropzone",
      "multi-step-form",
      "onboarding-checklist",
      "progress-bar",
      "tabs"
    ]
  },
  "files": [
    {
      "path": "src/registry/blocks/onboarding-flow.tsx",
      "type": "registry:component",
      "target": "components/motion-lexicon/blocks/onboarding-flow.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport { MultiStepForm } from \"@/components/motion-lexicon/multi-step-form\";\nimport { OnboardingChecklist } from \"@/components/motion-lexicon/onboarding-checklist\";\nimport { FileDropzone } from \"@/components/motion-lexicon/file-dropzone\";\nimport { Drawer } from \"@/components/motion-lexicon/drawer\";\nimport { ProgressBar } from \"@/components/motion-lexicon/progress-bar\";\nimport { Tabs } from \"@/components/motion-lexicon/tabs\";\n\ntype Locale = \"zh\" | \"en\";\nexport type OnboardingFlowBlockProps = { locale?: Locale; className?: string };\n\nexport function OnboardingFlowBlock({ locale = \"en\", className = \"\" }: OnboardingFlowBlockProps) {\n  const copy = locale === \"zh\" ? zh : en;\n  const reduced = useReducedMotion() === true;\n  const [workspace, setWorkspace] = useState(\"Northstar\");\n  const [files, setFiles] = useState<string[]>([]);\n  const [complete, setComplete] = useState(false);\n  const [helpOpen, setHelpOpen] = useState(false);\n  const steps = [{ id: \"workspace\", title: copy.stepWorkspace, description: copy.stepWorkspaceCopy, content: <label className=\"block\"><span className=\"sr-only\">{copy.workspace}</span><input value={workspace} onChange={(event) => setWorkspace(event.target.value)} className=\"min-h-11 w-full rounded-xl border border-neutral-200 bg-[#fafafa] px-3 text-[12px] outline-none focus-visible:ring-2 focus-visible:ring-[#4568ff]\" /></label>, validate: () => workspace.trim() ? null : copy.workspaceError }, { id: \"import\", title: copy.stepImport, description: copy.stepImportCopy, content: <FileDropzone label={copy.importLabel} accept=\".csv,.pdf,.md\" maxFiles={3} onFiles={(next) => setFiles(next.map((file) => file.name))} /> }, { id: \"invite\", title: copy.stepInvite, description: copy.stepInviteCopy, content: <div className=\"rounded-xl border border-neutral-200 bg-[#fafafa] p-3 text-[11px] text-neutral-600\"><span className=\"font-mono text-[9px] text-neutral-400\">TEAM</span><div className=\"mt-3 flex items-center justify-between\"><span>Mina · Editor</span><span className=\"rounded-full bg-emerald-100 px-2 py-1 text-[9px] text-emerald-800\">{copy.ready}</span></div><div className=\"mt-2 flex items-center justify-between\"><span>Noah · Producer</span><span className=\"rounded-full bg-emerald-100 px-2 py-1 text-[9px] text-emerald-800\">{copy.ready}</span></div></div> }];\n  const progress = complete ? 100 : files.length ? 66 : workspace.trim() ? 33 : 0;\n  return (\n    <section data-page-block=\"onboarding-flow\" className={`w-full overflow-hidden rounded-[18px] border border-neutral-200 bg-[#f7f7f5] text-[#242424] dark:border-white/10 dark:bg-[#151515] dark:text-neutral-100 ${className}`}>\n      <header className=\"flex min-h-16 items-center justify-between gap-4 border-b border-neutral-200 bg-white px-5 sm:px-7 dark:border-white/10 dark:bg-[#1b1b1b]\">\n        <a href=\"#onboarding-home\" className=\"flex min-h-11 items-center gap-2 text-[14px] font-semibold tracking-[-.03em] outline-none focus-visible:ring-2 focus-visible:ring-[#4568ff]\"><span className=\"grid size-8 place-items-center rounded-[9px] bg-[#242424] text-white\">A</span>Arc</a>\n        <span className=\"font-mono text-[9px] tracking-[.14em] text-neutral-400\">{complete ? copy.complete : copy.setup}</span>\n        <button type=\"button\" onClick={() => setComplete(false)} className=\"min-h-11 rounded-lg px-3 text-[11px] font-medium text-neutral-600 outline-none focus-visible:ring-2 focus-visible:ring-[#4568ff] dark:text-neutral-300\">{copy.restart}</button>\n      </header>\n      <div id=\"onboarding-home\" className=\"grid min-h-[650px] gap-6 p-4 sm:p-6 lg:grid-cols-[minmax(0,1.1fr)_minmax(300px,.9fr)] lg:p-9\">\n        <div className=\"min-w-0\"><span className=\"font-mono text-[9px] tracking-[.16em] text-neutral-400\">{copy.eyebrow}</span><h1 className=\"mt-3 max-w-[12ch] text-[clamp(34px,5vw,54px)] font-semibold leading-[.9] tracking-[-.06em]\">{copy.title}</h1><p className=\"mt-5 max-w-[48ch] text-[13px] leading-6 text-neutral-600 dark:text-neutral-300\">{copy.intro}</p><div className=\"mt-7 max-w-xl\"><MultiStepForm steps={steps} label={copy.setup} submitLabel={copy.finish} onSubmit={() => new Promise<void>((resolve) => { window.setTimeout(() => { setComplete(true); resolve(); }, reduced ? 0 : 350); })} /></div>{files.length ? <p role=\"status\" className=\"mt-3 max-w-xl rounded-xl bg-blue-50 px-3 py-2 text-[11px] text-blue-700\">{copy.imported}: {files.join(\", \")}</p> : null}</div>\n        <aside className=\"grid content-start gap-4\">\n          <ProgressBar value={progress} label={copy.setup} completeLabel={copy.complete} pendingLabel={copy.setup} />\n          <Tabs items={[{ value: \"steps\", label: copy.setup }, { value: \"help\", label: copy.help }]} label={copy.setup} renderPanel={(value) => <p className=\"text-[11px] leading-5 text-neutral-600 dark:text-neutral-300\">{value === \"steps\" ? copy.intro : copy.helpCopy}</p>} />\n          <AnimatePresence mode=\"wait\" initial={false}>{complete ? <motion.section key=\"complete\" initial={reduced ? false : { opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} className=\"rounded-[16px] bg-[#242424] p-5 text-white\"><span className=\"grid size-10 place-items-center rounded-full bg-[#dff0bf] text-[#1e2d1d]\">✓</span><h2 className=\"mt-6 text-[24px] tracking-[-.05em]\">{copy.doneTitle}</h2><p className=\"mt-3 text-[11px] leading-5 text-white/65\">{copy.doneCopy}</p><button type=\"button\" onClick={() => setComplete(false)} className=\"mt-6 min-h-11 w-full rounded-xl bg-white px-3 text-[11px] font-semibold text-[#242424] outline-none focus-visible:ring-2 focus-visible:ring-[#8eb9ff]\">{copy.restart}</button></motion.section> : <motion.div key=\"checklist\" initial={reduced ? false : { opacity: 0, y: -8 }} animate={{ opacity: 1, y: 0 }}><OnboardingChecklist title={copy.checklist} items={[{ id: \"workspace\", title: copy.checkWorkspace, detail: workspace || copy.unnamed, complete: Boolean(workspace) }, { id: \"import\", title: copy.checkImport, detail: files.length ? files[0] : copy.checkImportCopy }, { id: \"invite\", title: copy.checkInvite, detail: copy.checkInviteCopy }]} /></motion.div>}</AnimatePresence>\n          <section className=\"rounded-[16px] border border-neutral-200 bg-white p-4 text-[11px] dark:border-white/10 dark:bg-white/5\"><span className=\"font-mono text-[9px] tracking-[.14em] text-neutral-400\">{copy.help}</span><p className=\"mt-2 leading-5 text-neutral-600 dark:text-neutral-300\">{copy.helpCopy}</p><button type=\"button\" onClick={() => setHelpOpen(true)} className=\"mt-3 min-h-11 rounded-lg border border-neutral-200 px-3 font-medium outline-none focus-visible:ring-2 focus-visible:ring-[#4568ff] dark:border-white/15\">{copy.contact}</button></section>\n        </aside>\n      </div>\n      <Drawer open={helpOpen} onOpenChange={setHelpOpen} title={copy.help} description={copy.helpCopy} side=\"right\"><p className=\"text-[12px] leading-6 text-neutral-600 dark:text-neutral-300\">{copy.contact}</p></Drawer>\n    </section>\n  );\n}\nconst en = { setup: \"SETUP\", complete: \"SETUP COMPLETE\", restart: \"Restart\", eyebrow: \"Welcome to Arc\", title: \"Make your first workspace feel like yours.\", intro: \"Name the space, bring in the working material, and invite the people who will carry the first release with you.\", stepWorkspace: \"Name your workspace\", stepWorkspaceCopy: \"Use the team or project name people already recognize.\", workspace: \"Workspace name\", workspaceError: \"Add a workspace name to continue.\", stepImport: \"Bring in a working file\", stepImportCopy: \"A brief, a note, or the first data export is enough to begin.\", importLabel: \"Drop a brief or browse files\", stepInvite: \"Confirm the first collaborators\", stepInviteCopy: \"You can add more people after the first shared space is ready.\", ready: \"Ready\", finish: \"Create workspace\", imported: \"Ready to import\", checklist: \"Your first session\", checkWorkspace: \"Name the workspace\", unnamed: \"Choose a name\", checkImport: \"Bring in a working file\", checkImportCopy: \"Optional for now\", checkInvite: \"Confirm collaborators\", checkInviteCopy: \"2 people ready\", doneTitle: \"Your workspace is ready.\", doneCopy: \"Northstar has a home, a starting file and its first collaborators. Open the workspace when you are ready to make the next decision.\", help: \"NEED A HAND?\", helpCopy: \"Keep this setup lightweight. You can revisit files, roles and notifications later.\", contact: \"Contact support\" };\nconst zh = { setup: \"设置\", complete: \"设置完成\", restart: \"重新开始\", eyebrow: \"欢迎来到 Arc\", title: \"让第一个工作区从一开始就属于你。\", intro: \"为它命名，带入正在使用的材料，再邀请会和你共同推进首个版本的人。\", stepWorkspace: \"命名工作区\", stepWorkspaceCopy: \"使用团队已经熟悉的项目或组织名称。\", workspace: \"工作区名称\", workspaceError: \"请先填写工作区名称。\", stepImport: \"导入工作文件\", stepImportCopy: \"一份简报、一条笔记或第一份数据导出都足够开始。\", importLabel: \"拖入简报或浏览文件\", stepInvite: \"确认首批协作者\", stepInviteCopy: \"首个共享空间准备好后，还可以继续添加成员。\", ready: \"已就绪\", finish: \"创建工作区\", imported: \"准备导入\", checklist: \"你的第一次会话\", checkWorkspace: \"命名工作区\", unnamed: \"选择一个名称\", checkImport: \"导入工作文件\", checkImportCopy: \"暂时可选\", checkInvite: \"确认协作者\", checkInviteCopy: \"2 人已就绪\", doneTitle: \"工作区已准备好。\", doneCopy: \"Northstar 已拥有一个主页、一个起始文件和最初的协作者。准备好做下一个决定时，打开工作区即可。\", help: \"需要帮助？\", helpCopy: \"保持这次设置足够轻量。文件、角色和通知都可以稍后再调整。\", contact: \"联系支持\" };\n"
    }
  ]
}
