Setup Wizard

Multi-step onboarding wizard with profile setup, preferences, and skippable optional steps. Built with React Context for state management.

Preview

Features

  • 4-step flow: Welcome → Profile → Preferences → Complete
  • React Context for centralized state management
  • Simple dot indicator for progress
  • Skip button for optional steps (Profile, Preferences)
  • Back/Continue navigation
  • Form data persistence across steps
  • Compact theme toggle (Light/Dark/System)
  • Clean notification toggles
  • onComplete callback with collected data
  • Fully accessible with keyboard navigation

Install Summary

This kit will add the following files and dependencies to your project. Download the bundle and extract it into your project root.

Component Files

FilePath
setup-wizard.tsxcomponents/onboarding/setup-wizard/setup-wizard.tsx
setup-wizard-context.tsxcomponents/onboarding/setup-wizard/setup-wizard-context.tsx
wizard-steps.tsxcomponents/onboarding/setup-wizard/wizard-steps.tsx
step-welcome.tsxcomponents/onboarding/setup-wizard/step-welcome.tsx
step-profile.tsxcomponents/onboarding/setup-wizard/step-profile.tsx
step-preferences.tsxcomponents/onboarding/setup-wizard/step-preferences.tsx
step-complete.tsxcomponents/onboarding/setup-wizard/step-complete.tsx
types.tscomponents/onboarding/setup-wizard/types.ts
index.tscomponents/onboarding/setup-wizard/index.ts

Utility Files

FilePath
design-tokens.tslib/design-tokens.ts

Dependencies

Install these dependencies before using the component:

Terminal
bash
npx shadcn@latest add dialog button input label
Terminal
bash
npm install @phosphor-icons/react

Installation

Download the complete bundle as a ZIP file, or copy the text bundle to your clipboard:

Component Files

The component consists of the following files:

1. setup-wizard.tsx

setup-wizard.tsx
tsx
"use client";

import {
  Dialog,
  DialogContent,

2. setup-wizard-context.tsx

setup-wizard-context.tsx
tsx
"use client";

import {
  createContext,
  useContext,

3. wizard-steps.tsx

wizard-steps.tsx
tsx
"use client";

import { cn } from "@/lib/utils";
import { useSetupWizard, STEPS } from "./setup-wizard-context";

4. step-welcome.tsx

step-welcome.tsx
tsx
"use client";

import { RocketLaunch, ArrowRight } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";
import { radius } from "@/lib/design-tokens";

5. step-profile.tsx

step-profile.tsx
tsx
"use client";

import { User, ArrowLeft, ArrowRight } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

6. step-preferences.tsx

step-preferences.tsx
tsx
"use client";

import { Gear as Settings, ArrowLeft, ArrowRight } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";

7. step-complete.tsx

step-complete.tsx
tsx
"use client";

import { SealCheck as CheckCircle2 } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

8. types.ts

types.ts
tsx
export type SetupStep = "welcome" | "profile" | "preferences" | "complete";

export interface StepConfig {
  id: SetupStep;
  title: string;

9. index.ts

index.ts
tsx
export { SetupWizard } from "./setup-wizard";
export { SetupWizardProvider, useSetupWizard, STEPS } from "./setup-wizard-context";
export type {
  SetupStep,
  StepConfig,
  ProfileData,
  PreferencesData,
  WizardData,
  SetupWizardProps,
  SetupWizardContextValue,
} from "./types";

Shared Utilities

This component uses shared utility functions. These are included in the bundle above:

design-tokens.ts

design-tokens.ts
tsx
// Border radius
export const radius = {
  card: "rounded-xl",
  badge: "rounded-full",
  button: "rounded-lg",

Usage

app/onboarding.tsx
tsx
import { useState } from "react";
import { SetupWizard, type WizardData } from "@/components/onboarding/setup-wizard";

function OnboardingPage() {
  const [open, setOpen] = useState(true);

SetupWizard Props

PropTypeDefault
openbooleanrequired
onOpenChange(open: boolean) => voidrequired
onComplete(data: WizardData) => void-
initialDataPartial<WizardData>-