{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "onboarding-checklist",
  "title": "Onboarding Checklist",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-svelte/blocks/onboarding-checklist/OnboardingChecklist.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Component } from 'svelte'\n\n  export interface OnboardingTask {\n    id: string\n    title: string\n    description: string\n    icon: Component\n    done: boolean\n  }\n\n  export interface OnboardingChecklistProps {\n    /** Seed every task as done so the success panel can be previewed in isolation. */\n    initialComplete?: boolean\n    class?: string\n  }\n</script>\n\n<script lang=\"ts\">\n  import { Bell, BookOpen, Building2, Check, ChevronRight, Database, Users, X } from '@lucide/svelte'\n  import { cn } from '$lib/utils'\n  import { Button } from '$lib/components/ui/button'\n  import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '$lib/components/ui/card'\n  import { Progress } from '$lib/components/ui/progress'\n\n  let { initialComplete = false, class: className }: OnboardingChecklistProps = $props()\n\n  const baseTasks: Omit<OnboardingTask, '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\n  let tasks = $state<OnboardingTask[]>(\n    baseTasks.map((task, index) => ({\n      ...task,\n      done: initialComplete || index < 3,\n    })),\n  )\n\n  let open = $state(true)\n\n  const completed = $derived(tasks.filter((task) => task.done).length)\n  const total = $derived(tasks.length)\n  const percent = $derived(Math.round((completed / total) * 100))\n  const allDone = $derived(completed === total)\n\n  function toggle(id: string) {\n    const task = tasks.find((t) => t.id === id)\n    if (task) task.done = !task.done\n  }\n</script>\n\n<div\n  data-slot=\"onboarding-checklist\"\n  class={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 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 value={percent} />\n      </div>\n\n      {#if allDone}\n        <div 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      {:else}\n        <div class=\"-mx-2 divide-y\">\n          {#each tasks as task (task.id)}\n            {@const Icon = task.icon}\n            <button\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              onclick={() => toggle(task.id)}\n            >\n              {#if task.done}\n                <span\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              {:else}\n                <span\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                  <Icon class=\"size-4\" aria-hidden=\"true\" />\n                </span>\n              {/if}\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          {/each}\n        </div>\n      {/if}\n    </CardContent>\n    <CardFooter class=\"justify-between\">\n      {#if !allDone}\n        <Button variant=\"ghost\" size=\"sm\" onclick={() => (open = false)}>Skip for now</Button>\n      {:else}\n        <span aria-hidden=\"true\"></span>\n      {/if}\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        onclick={() => (open = false)}\n      >\n        <X class=\"text-muted-foreground size-4\" aria-hidden=\"true\" />\n      </button>\n    </CardFooter>\n  </Card>\n</div>\n",
      "type": "registry:block",
      "target": "~/src/lib/components/blocks/onboarding-checklist/OnboardingChecklist.svelte"
    }
  ],
  "dependencies": [
    "@lucide/svelte"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/svelte/button.json",
    "https://uipkge.dev/r/svelte/card.json",
    "https://uipkge.dev/r/svelte/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"
  ]
}