{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "onboarding-demo",
  "type": "registry:component",
  "registryDependencies": [
    "onboarding"
  ],
  "files": [
    {
      "path": "registry/default/example/onboarding-demo.tsx",
      "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport Image from \"next/image\"\nimport {\n  ArrowLeft,\n  BookOpen,\n  Building,\n  Building2,\n  CircleDashed,\n  Code2,\n  Download,\n  Megaphone,\n  Palette,\n  Rocket,\n  TrendingUp,\n} from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n} from \"@/components/ui/dialog\"\n\nimport {\n  ChoiceGroup,\n  FeatureCarousel,\n  Onboarding,\n  TipsList,\n  useOnboarding,\n} from \"../ui/onboarding\"\n\nconst STEP_CONFIG = [\n  {\n    title: \"Welcome to AI SDK Agents\",\n    description: \"Start shipping ai agents that actually work.\",\n  },\n  {\n    title: \"Personalize your experience\",\n    description: \"Tell us about yourself so we can tailor the experience\",\n  },\n  {\n    title: \"You're ready to go!\",\n    description: \"A few tips to get the most out of AI SDK Agents\",\n  },\n]\n\nexport const FEATURES = [\n  {\n    id: \"source-code\",\n    icon: Code2, // swap Sparkles → Code2\n    title: \"Full Stack Source Code\",\n    description:\n      \"Browse and copy the complete source code for every pattern directly from the Source Code tab.\",\n    image: \"/component-images/onboarding/onboarding-source-code.png\",\n  },\n  {\n    id: \"skills\",\n    icon: BookOpen, // swap ImagePlus → BookOpen (or similar)\n    title: \"Copy Skills & Critical Files\",\n    description:\n      \"Copy agent skills and critical files to supercharge your AI-powered workflows.\",\n    image: \"/component-images/onboarding/onboarding-skills.png\",\n  },\n  {\n    id: \"download\",\n    icon: Download, // swap Lightbulb → Download\n    title: \"Download as Next.js App\",\n    description:\n      \"Download any pattern as a fully working Next.js application, ready to run locally.\",\n    image: \"/component-images/onboarding/onboarding-nextjs.png\",\n  },\n] as const\n\nexport const ROLES = [\n  { id: \"designer\", label: \"Designer\", icon: Palette },\n  { id: \"founder\", label: \"Founder\", icon: Rocket },\n  { id: \"sales\", label: \"Sales\", icon: TrendingUp },\n  { id: \"freelancer\", label: \"Freelancer\", icon: Building2 },\n  { id: \"marketing\", label: \"Marketing\", icon: Megaphone },\n  { id: \"developer\", label: \"Developer\", icon: Code2 },\n  { id: \"agency\", label: \"Agency\", icon: Building },\n  { id: \"other\", label: \"Other\", icon: CircleDashed },\n] as const\n\nexport const GOALS = [\n  { id: \"ai-agents\", label: \"Building AI agents\" },\n  { id: \"chatbots\", label: \"Chatbots & assistants\" },\n  { id: \"automation\", label: \"Workflow automation\" },\n  { id: \"rag\", label: \"RAG & search\" },\n  { id: \"prototyping\", label: \"Rapid prototyping\" },\n  { id: \"other\", label: \"Something else\" },\n] as const\n\nexport const TIPS = [\n  {\n    number: 1,\n    text: \"Browse patterns by use case to find the right agent architecture for your project.\",\n  },\n  {\n    number: 2,\n    text: \"Use the Download as Next.js App button to get a fully working local project in seconds.\",\n  },\n  {\n    number: 3,\n    text: \"Copy skills and critical files to quickly skill up claude code and cursor.\",\n  },\n] as const\n\nexport const TOTAL_STEPS = 3\nexport const MAX_STEP_VALUE = FEATURES.length - 1\n\n// ============================================================================\n// Headless Primitives Demo (composable, uses shadcn tokens)\n// ============================================================================\n\nexport default function OnboardingDemo() {\n  return <HeadlessOnboardingDemo />\n}\n\nexport function HeadlessOnboardingDemo() {\n  const [open, setOpen] = useState(false)\n  const [selectedRole, setSelectedRole] = useState<string | null>(null)\n  const [selectedGoal, setSelectedGoal] = useState<string | null>(null)\n\n  return (\n    <div className=\"flex flex-col items-center gap-4\">\n      <Button onClick={() => setOpen(true)} variant=\"outline\">\n        Open Headless Onboarding\n      </Button>\n      <Dialog onOpenChange={setOpen} open={open}>\n        <DialogContent\n          className=\"w-full max-w-[calc(100dvw-2rem)] border-none bg-transparent p-0 shadow-none sm:max-w-3xl\"\n          showCloseButton={false}\n        >\n          <div className=\"bg-muted w-full rounded-2xl p-[2px] md:p-2\">\n            <Onboarding\n              canGoNext={(step) =>\n                step === 1 ||\n                (step === 2 && selectedGoal !== null) ||\n                step === 3\n              }\n              className=\"relative overflow-hidden\"\n              maxStepValue={MAX_STEP_VALUE}\n              onComplete={() => setOpen(false)}\n              totalSteps={3}\n            >\n              <HeadlessOnboardingHeader />\n              <div className=\"my-8 min-h-[280px]\">\n                <Onboarding.Step step={1}>\n                  <HeadlessFeatureStep />\n                </Onboarding.Step>\n                <Onboarding.Step step={2}>\n                  <HeadlessRoleStep\n                    onGoalSelect={setSelectedGoal}\n                    onRoleSelect={setSelectedRole}\n                    selectedGoal={selectedGoal}\n                    selectedRole={selectedRole}\n                  />\n                </Onboarding.Step>\n                <Onboarding.Step step={3}>\n                  <HeadlessTipsStep />\n                </Onboarding.Step>\n              </div>\n              <Onboarding.Navigation completeLabel=\"Start Creating\" />\n            </Onboarding>\n          </div>\n        </DialogContent>\n      </Dialog>\n    </div>\n  )\n}\n\nfunction HeadlessOnboardingHeader() {\n  const { currentStep } = useOnboarding()\n  const config = STEP_CONFIG[currentStep - 1]\n\n  return (\n    <DialogHeader className=\"!text-center\">\n      {/* <DialogTitle className=\"font-normal font-pixel-square text-3xl text-foreground\"> */}\n      <DialogTitle className=\"text-foreground font-semibold tracking-tighter md:text-3xl\">\n        {config.title}\n      </DialogTitle>\n      <DialogDescription className=\"text-muted-foreground md:text-base\">\n        {config.description}\n      </DialogDescription>\n      <div className=\"pt-3\">\n        <Onboarding.StepIndicator />\n      </div>\n    </DialogHeader>\n  )\n}\n\nfunction HeadlessFeatureStep() {\n  const { stepValue, setStepValue } = useOnboarding()\n\n  return (\n    <div className=\"flex flex-col gap-4 md:flex-row md:gap-6\">\n      <FeatureCarousel\n        className=\"order-2 flex w-full flex-col gap-3 md:order-1 md:w-1/2\"\n        onValueChange={setStepValue}\n        totalItems={FEATURES.length}\n        value={stepValue}\n      >\n        {FEATURES.map((feature, index) => {\n          const Icon = feature.icon\n          const isActive = stepValue === index\n          return (\n            <FeatureCarousel.Item index={index} key={feature.id}>\n              <div\n                className={cn(\n                  \"flex items-start gap-3 rounded-xl border p-4 text-left transition-all duration-200\",\n                  isActive\n                    ? \"border-primary/30 bg-primary/10\"\n                    : \"hover:bg-muted border-transparent\"\n                )}\n              >\n                <Icon\n                  className={cn(\n                    \"mt-0.5 size-5 shrink-0\",\n                    isActive ? \"text-primary\" : \"text-muted-foreground\"\n                  )}\n                />\n                <div>\n                  <p className=\"text-foreground text-sm font-medium\">\n                    {feature.title}\n                  </p>\n                  {isActive && (\n                    <p className=\"text-muted-foreground mt-1 text-sm leading-relaxed\">\n                      {feature.description}\n                    </p>\n                  )}\n                </div>\n              </div>\n            </FeatureCarousel.Item>\n          )\n        })}\n      </FeatureCarousel>\n      <div className=\"order-1 w-full md:order-2 md:w-1/2\">\n        <div className=\"bg-muted relative aspect-[4/3] overflow-hidden rounded-xl border\">\n          <Image\n            alt={FEATURES[stepValue].title}\n            className=\"object-cover transition-opacity duration-300\"\n            fill\n            sizes=\"(max-width: 768px) 100vw, 40vw\"\n            src={FEATURES[stepValue].image}\n          />\n        </div>\n      </div>\n    </div>\n  )\n}\n\nfunction HeadlessRoleStep({\n  selectedRole,\n  onRoleSelect,\n  selectedGoal,\n  onGoalSelect,\n}: {\n  selectedRole: string | null\n  onRoleSelect: (v: string) => void\n  selectedGoal: string | null\n  onGoalSelect: (v: string) => void\n}) {\n  const { handleNext } = useOnboarding()\n  const [question, setQuestion] = useState(selectedGoal ? 2 : 1)\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n      {question === 1 ? (\n        <div className=\"flex flex-col gap-4\" key=\"q1\">\n          <div className=\"flex items-center gap-2\">\n            <span className=\"bg-muted text-muted-foreground inline-flex size-6 items-center justify-center rounded-lg text-sm\">\n              1\n            </span>\n            <span className=\"text-foreground text-base font-medium\">\n              What best describes you?\n            </span>\n          </div>\n          <ChoiceGroup\n            className=\"grid grid-cols-2 gap-2 sm:gap-3 md:grid-cols-3\"\n            name=\"Select your role\"\n            onValueChange={(v) => {\n              onRoleSelect(v)\n              setTimeout(() => setQuestion(2), 300)\n            }}\n            orientation=\"grid\"\n            value={selectedRole}\n          >\n            {ROLES.map((role) => {\n              const Icon = role.icon\n              const isSelected = selectedRole === role.id\n              return (\n                <ChoiceGroup.Item\n                  className={cn(\n                    \"flex cursor-pointer items-center gap-2.5 rounded-xl border px-4 py-3 text-left text-sm transition-all duration-200\",\n                    isSelected\n                      ? \"border-primary/30 bg-primary/10 text-foreground\"\n                      : \"border-border bg-background text-foreground hover:bg-muted\"\n                  )}\n                  key={role.id}\n                  value={role.id}\n                >\n                  <Icon className=\"text-muted-foreground size-4 shrink-0\" />\n                  <span>{role.label}</span>\n                </ChoiceGroup.Item>\n              )\n            })}\n          </ChoiceGroup>\n          <p className=\"text-muted-foreground text-sm\">Question 1 of 2</p>\n        </div>\n      ) : (\n        <div className=\"flex flex-col gap-4\" key=\"q2\">\n          <div className=\"flex items-center gap-2\">\n            <span className=\"bg-muted text-muted-foreground inline-flex size-6 items-center justify-center rounded-lg text-sm\">\n              2\n            </span>\n            <span className=\"text-foreground text-base font-medium\">\n              What do you want to create?\n            </span>\n          </div>\n          <ChoiceGroup\n            className=\"grid grid-cols-2 gap-2 sm:gap-3\"\n            name=\"Select your goal\"\n            onValueChange={(v) => {\n              onGoalSelect(v)\n              setTimeout(() => handleNext(), 300)\n            }}\n            orientation=\"grid\"\n            value={selectedGoal}\n          >\n            {GOALS.map((goal) => {\n              const isSelected = selectedGoal === goal.id\n              return (\n                <ChoiceGroup.Item\n                  className={cn(\n                    \"flex cursor-pointer items-center gap-2.5 rounded-xl border px-4 py-3 text-left text-sm transition-all duration-200\",\n                    isSelected\n                      ? \"border-primary/30 bg-primary/10 text-foreground\"\n                      : \"border-border bg-background text-foreground hover:bg-muted\"\n                  )}\n                  key={goal.id}\n                  value={goal.id}\n                >\n                  <span>{goal.label}</span>\n                </ChoiceGroup.Item>\n              )\n            })}\n          </ChoiceGroup>\n          <div className=\"flex items-center justify-between\">\n            <Button\n              className=\"text-muted-foreground hover:text-foreground text-sm transition-colors\"\n              onClick={() => setQuestion(1)}\n              type=\"button\"\n              size=\"sm\"\n              variant=\"ghost\"\n            >\n              <ArrowLeft className=\"size-4\" />\n              Back to question 1\n            </Button>\n            <p className=\"text-muted-foreground text-sm\">Question 2 of 2</p>\n          </div>\n        </div>\n      )}\n    </div>\n  )\n}\n\nfunction HeadlessTipsStep() {\n  return (\n    <div className=\"flex flex-col gap-4 md:flex-row md:items-stretch md:gap-6\">\n      <div className=\"order-2 w-full md:order-1 md:w-1/2\">\n        <TipsList\n          className=\"[&_[data-slot=tips-list-title]]:text-muted-foreground flex h-full flex-col [&_[data-slot=tips-list-items]]:flex [&_[data-slot=tips-list-items]]:h-full [&_[data-slot=tips-list-items]]:flex-col [&_[data-slot=tips-list-items]]:justify-between [&_[data-slot=tips-list-items]]:gap-4 [&_[data-slot=tips-list-title]]:not-sr-only [&_[data-slot=tips-list-title]]:mb-4 [&_[data-slot=tips-list-title]]:text-xs [&_[data-slot=tips-list-title]]:font-semibold [&_[data-slot=tips-list-title]]:tracking-wider [&_[data-slot=tips-list-title]]:uppercase\"\n          title=\"Tips\"\n        >\n          {TIPS.map((tip) => (\n            <TipsList.Item\n              className=\"[&_[data-slot=tips-list-item-number]]:bg-muted [&_[data-slot=tips-list-item-number]]:text-muted-foreground flex items-start gap-3 [&_[data-slot=tips-list-item-number]]:inline-flex [&_[data-slot=tips-list-item-number]]:size-6 [&_[data-slot=tips-list-item-number]]:shrink-0 [&_[data-slot=tips-list-item-number]]:items-center [&_[data-slot=tips-list-item-number]]:justify-center [&_[data-slot=tips-list-item-number]]:rounded-lg [&_[data-slot=tips-list-item-number]]:text-sm\"\n              key={tip.number}\n              number={tip.number}\n            >\n              <p className=\"text-foreground text-sm leading-relaxed\">\n                {tip.text}\n              </p>\n            </TipsList.Item>\n          ))}\n        </TipsList>\n      </div>\n      <div className=\"order-1 w-full md:order-2 md:w-1/2\">\n        <div className=\"bg-background relative aspect-video w-full overflow-hidden rounded-xl border md:aspect-[4/3]\">\n          <Image\n            src=\"/component-images/onboarding/onboarding-tip1.png\"\n            alt=\"Onboarding\"\n            fill\n            sizes=\"(max-width: 768px) 100vw, 40vw\"\n            className=\"object-cover\"\n          />\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component"
    }
  ]
}