{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "onboarding-checklist",
  "title": "Onboarding Checklist",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/onboarding-checklist/OnboardingChecklist.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { Bell, BookOpen, Building2, Check, ChevronRight, Database, Users, X } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Progress } from '@/components/ui/progress'\n\ninterface Task {\n  id: string\n  title: string\n  description: string\n  icon: LucideIcon\n}\n\nconst baseTasks: Task[] = [\n  {\n    id: 'workspace',\n    title: 'Create workspace',\n    description: 'Name your team space and pick a URL.',\n    icon: Building2,\n  },\n  {\n    id: 'teammates',\n    title: 'Invite teammates',\n    description: 'Bring in the people you work with.',\n    icon: Users,\n  },\n  {\n    id: 'data',\n    title: 'Connect your data',\n    description: 'Sync sources so insights flow in automatically.',\n    icon: Database,\n  },\n  {\n    id: 'alerts',\n    title: 'Set up alerts',\n    description: 'Get notified when metrics move.',\n    icon: Bell,\n  },\n  {\n    id: 'api',\n    title: 'Explore API docs',\n    description: 'Learn the endpoints and ship your first request.',\n    icon: BookOpen,\n  },\n]\n\nexport interface OnboardingChecklistProps {\n  /** Seed every task as done so the success panel can be previewed in isolation. */\n  initialComplete?: boolean\n  className?: string\n}\n\nexport function OnboardingChecklist({ initialComplete = false, className }: OnboardingChecklistProps) {\n  const [tasks, setTasks] = React.useState(() =>\n    baseTasks.map((task, index) => ({ ...task, done: initialComplete || index < 3 })),\n  )\n  const [open, setOpen] = React.useState(true)\n\n  const completed = tasks.filter((task) => task.done).length\n  const total = tasks.length\n  const percent = Math.round((completed / total) * 100)\n  const allDone = completed === total\n\n  function toggle(id: string) {\n    setTasks((prev) => prev.map((task) => (task.id === id ? { ...task, done: !task.done } : task)))\n  }\n\n  return (\n    <div\n      data-slot=\"onboarding-checklist\"\n      className={cn(\n        'mx-auto w-full max-w-md transition-[opacity,translate] duration-200 ease-out motion-reduce:transition-none',\n        !open && 'pointer-events-none translate-y-1 opacity-0',\n        className,\n      )}\n    >\n      <Card>\n        <CardHeader>\n          <CardTitle>Get started</CardTitle>\n          <CardDescription>Finish these steps to unlock everything your workspace can do.</CardDescription>\n        </CardHeader>\n        <CardContent className=\"space-y-4\">\n          <div className=\"space-y-2\">\n            <div className=\"flex items-center justify-between\">\n              <p className=\"text-muted-foreground text-xs\">\n                <span className=\"text-foreground font-medium\">\n                  {completed} of {total}\n                </span>{' '}\n                complete\n              </p>\n              <p className=\"text-muted-foreground text-xs tabular-nums\">{percent}%</p>\n            </div>\n            <Progress value={percent} />\n          </div>\n\n          {allDone ? (\n            <div className=\"space-y-4 py-6 text-center\">\n              <div className=\"border-success/30 bg-success/10 text-success mx-auto flex size-16 items-center justify-center rounded-full border shadow-xs\">\n                <Check className=\"size-8\" aria-hidden=\"true\" />\n              </div>\n              <div>\n                <p className=\"text-lg font-semibold\">You're all set</p>\n                <p className=\"text-muted-foreground mt-1 text-sm\">\n                  Every step is complete — your workspace is ready to go.\n                </p>\n              </div>\n            </div>\n          ) : (\n            <div className=\"-mx-2 divide-y\">\n              {tasks.map((task) => {\n                const Icon = task.icon\n                return (\n                  <button\n                    key={task.id}\n                    type=\"button\"\n                    role=\"checkbox\"\n                    aria-checked={task.done}\n                    onClick={() => toggle(task.id)}\n                    className=\"group hover:bg-muted/50 focus-visible:ring-ring flex w-full items-center gap-3 rounded-lg p-3 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n                  >\n                    {task.done ? (\n                      <span className=\"bg-primary text-primary-foreground flex size-9 shrink-0 items-center justify-center rounded-md shadow-xs\">\n                        <Check className=\"size-4\" aria-hidden=\"true\" />\n                      </span>\n                    ) : (\n                      <span className=\"border-border bg-muted text-muted-foreground group-hover:bg-background group-hover:text-foreground flex size-9 shrink-0 items-center justify-center rounded-md border transition-colors\">\n                        <Icon className=\"size-4\" aria-hidden=\"true\" />\n                      </span>\n                    )}\n                    <span className=\"min-w-0 flex-1\">\n                      <span className={cn('block truncate text-sm font-medium', task.done && 'text-muted-foreground')}>\n                        {task.title}\n                      </span>\n                      <span className=\"text-muted-foreground mt-0.5 block truncate text-xs\">{task.description}</span>\n                    </span>\n                    <ChevronRight\n                      className=\"text-muted-foreground/50 size-4 shrink-0 transition-transform duration-200 group-hover:translate-x-0.5\"\n                      aria-hidden=\"true\"\n                    />\n                  </button>\n                )\n              })}\n            </div>\n          )}\n        </CardContent>\n        <CardFooter className=\"justify-between\">\n          {!allDone ? (\n            <Button variant=\"ghost\" size=\"sm\" onClick={() => setOpen(false)}>\n              Skip for now\n            </Button>\n          ) : (\n            <span aria-hidden=\"true\" />\n          )}\n          <button\n            type=\"button\"\n            aria-label=\"Dismiss checklist\"\n            onClick={() => setOpen(false)}\n            className=\"hover:bg-foreground/10 focus-visible:ring-ring rounded-md p-1.5 transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n          >\n            <X className=\"text-muted-foreground size-4\" aria-hidden=\"true\" />\n          </button>\n        </CardFooter>\n      </Card>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/OnboardingChecklist.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/progress.json"
  ],
  "description": "Progressive activation checklist card: header with title, an N of M complete counter and a linear Progress bar, tappable task rows with icon tiles, one-line descriptions and chevrons (completed tasks flip to a filled check tile with muted copy), a footer with a Skip for now ghost link and an X dismiss that fades the card out, and a success panel with a glowing check circle at 5 of 5. State is local — wire tasks to your own activation API.",
  "categories": [
    "auth",
    "app",
    "onboarding"
  ]
}