{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "onboarding-checklist",
  "title": "Onboarding Checklist",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/onboarding-checklist/OnboardingChecklist.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { Component } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport { Bell, BookOpen, Building2, Check, ChevronRight, Database, Users, X } from 'lucide-vue-next'\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: Component\n  done: boolean\n}\n\nconst props = withDefaults(\n  defineProps<{\n    /** Seed every task as done so the success panel can be previewed in isolation. */\n    initialComplete?: boolean\n    class?: HTMLAttributes['class']\n  }>(),\n  {\n    initialComplete: false,\n  },\n)\n\nconst baseTasks: Omit<Task, 'done'>[] = [\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\nconst tasks = ref<Task[]>(\n  baseTasks.map((task, index) => ({\n    ...task,\n    done: props.initialComplete || index < 3,\n  })),\n)\n\nconst open = ref(true)\n\nconst completed = computed(() => tasks.value.filter((task) => task.done).length)\nconst total = computed(() => tasks.value.length)\nconst percent = computed(() => Math.round((completed.value / total.value) * 100))\nconst allDone = computed(() => completed.value === total.value)\n\nfunction toggle(id: string) {\n  const task = tasks.value.find((t) => t.id === id)\n  if (task) task.done = !task.done\n}\n\nfunction dismiss() {\n  open.value = false\n}\n</script>\n\n<template>\n  <div\n    data-slot=\"onboarding-checklist\"\n    :class=\"\n      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        props.class,\n      )\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 class=\"space-y-4\">\n        <div class=\"space-y-2\">\n          <div class=\"flex items-center justify-between\">\n            <p class=\"text-muted-foreground text-xs\">\n              <span class=\"text-foreground font-medium\">{{ completed }} of {{ total }}</span>\n              complete\n            </p>\n            <p class=\"text-muted-foreground text-xs tabular-nums\">{{ percent }}%</p>\n          </div>\n          <Progress :model-value=\"percent\" />\n        </div>\n\n        <div v-if=\"allDone\" class=\"space-y-4 py-6 text-center\">\n          <div\n            class=\"border-success/30 bg-success/10 text-success mx-auto flex size-16 items-center justify-center rounded-full border shadow-xs\"\n          >\n            <Check class=\"size-8\" aria-hidden=\"true\" />\n          </div>\n          <div>\n            <p class=\"text-lg font-semibold\">You're all set</p>\n            <p class=\"text-muted-foreground mt-1 text-sm\">Every step is complete — your workspace is ready to go.</p>\n          </div>\n        </div>\n\n        <div v-else class=\"-mx-2 divide-y\">\n          <button\n            v-for=\"task in tasks\"\n            :key=\"task.id\"\n            type=\"button\"\n            role=\"checkbox\"\n            :aria-checked=\"task.done\"\n            class=\"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            @click=\"toggle(task.id)\"\n          >\n            <span\n              v-if=\"task.done\"\n              class=\"bg-primary text-primary-foreground flex size-9 shrink-0 items-center justify-center rounded-md shadow-xs\"\n            >\n              <Check class=\"size-4\" aria-hidden=\"true\" />\n            </span>\n            <span\n              v-else\n              class=\"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            >\n              <component :is=\"task.icon\" class=\"size-4\" aria-hidden=\"true\" />\n            </span>\n            <span class=\"min-w-0 flex-1\">\n              <span :class=\"cn('block truncate text-sm font-medium', task.done && 'text-muted-foreground')\">\n                {{ task.title }}\n              </span>\n              <span class=\"text-muted-foreground mt-0.5 block truncate text-xs\">{{ task.description }}</span>\n            </span>\n            <ChevronRight\n              class=\"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        </div>\n      </CardContent>\n      <CardFooter class=\"justify-between\">\n        <Button v-if=\"!allDone\" variant=\"ghost\" size=\"sm\" @click=\"dismiss\">Skip for now</Button>\n        <span v-else aria-hidden=\"true\"></span>\n        <button\n          type=\"button\"\n          aria-label=\"Dismiss checklist\"\n          class=\"hover:bg-foreground/10 focus-visible:ring-ring rounded-md p-1.5 transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n          @click=\"dismiss\"\n        >\n          <X class=\"text-muted-foreground size-4\" aria-hidden=\"true\" />\n        </button>\n      </CardFooter>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/OnboardingChecklist.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/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"
  ]
}