Build an Onboarding Progress Bar widget providing a checklist with progress percentage, step completion toggling, ManagedChecklist integration, and a persistent state callback. It enhances the existing managed-checklist.tsx with a progress header, percentage display, and onboarding-specific UX patterns.
Introduction
Overview
SaaS applications commonly display an onboarding checklist that guides new users through setup steps (create a project, invite a teammate, connect an integration). The design system provides ManagedChecklist for general-purpose checklists, but it lacks a progress header, percentage bar, completion celebration, and the persistent-state pattern needed for onboarding flows. Teams build these patterns from scratch.
Goals
Provide an OnboardingProgressBar widget with a visual progress bar and percentage display.
Integrate with ManagedChecklist for the step list with completion toggling.
Support a persistent state callback so completion state survives page refreshes.
Provide completion celebration (confetti or checkmark animation) when all steps are done.
Support collapsible mode so the checklist can be minimized after initial setup.
A bar showing completion percentage with “X of Y completed” text.
Step checklist
ManagedChecklist-based step list with toggleable completion per step.
Persistent state
onStateChange callback fires on every completion toggle; consumer persists to localStorage or API.
Completion celebration
Visual indicator (animated checkmark, confetti) when all steps are completed.
Collapsible mode
The checklist can collapse to show only the progress bar header.
Dismissible
An optional “Dismiss” action that hides the widget entirely (calls onDismiss callback).
Stories and tests
Storybook stories for all states; unit tests for progress calculation and state management.
Out of Scope
Item
Reason
Multi-page wizard
PanelWizard handles that pattern.
Step-specific content/forms
Steps are labels with optional descriptions; forms are in the application.
Analytics tracking
Consumer responsibility via callbacks.
Users and Pain Points
User
Pain Point
SaaS developers
Build onboarding checklists from scratch for every product; inconsistent patterns.
Product managers
Cannot easily A/B test onboarding flows without a standard widget.
New users
No visual indication of setup progress; unclear what steps remain.
Growth teams
Onboarding completion rates are hard to improve without a consistent, polished experience.
Definitions
Term
Definition
Onboarding step
A single setup task the user needs to complete (e.g., “Create your first project”).
Completion percentage
(completedSteps / totalSteps) * 100.
Persistent state
Step completion state that survives page navigation and browser refresh.
Dismissible
The widget can be permanently hidden by the user.
Current State
ManagedChecklist (src/components/widgets/managed-checklist.tsx): General-purpose checklist with ManagedListItem entries supporting checked state, edit mode, and term-definition variants. No progress bar, percentage, or onboarding-specific features.
ChecklistFoundation: Low-level primitives (ChecklistRow, ChecklistContainer, etc.) used by ManagedChecklist.
│ ├── Step 1: [check] "Create your first project" — description
│ ├── Step 2: [check] "Invite a team member" — description
│ └── ...
└── Completion celebration (when all done)
Progress Bar
A horizontal bar using the existing progress bar styles (or a simple div with bg-primary and width percentage). Animated fill using motion tokens.
Step List
Each step renders as a ManagedChecklist item (or a simplified version). Clicking a step toggles its completion. Optionally, clicking a step can navigate to the relevant page via an onStepClick callback.
Persistent State
The widget accepts completedStepIds: string[] (controlled) and fires onStateChange(completedStepIds) on every toggle. The consumer persists this array to localStorage, a cookie, or an API.
Completion
When all steps are completed, the progress bar fills to 100% and an animated checkmark or brief confetti animation plays. An optional “All done!” message replaces the step list.
Requirements
Requirement Priorities
Must Have: Progress bar with percentage, step list with toggleable completion, state change callback.
Should Have: Collapsible mode, dismissible, step click navigation callback.
Could Have: Completion celebration animation, “All done” message, step reordering.
Functional Requirements
ID
Requirement
Priority
FR-01
Widget displays a progress bar with fill proportional to completed steps.
Must
FR-02
”X of Y completed” text displays above or beside the progress bar.
Must
FR-03
Step list renders each step with a checkbox, title, and optional description.
Must
FR-04
Clicking a step checkbox toggles its completion state.
Must
FR-05
onStateChange callback fires with updated completedStepIds array on every toggle.
Must
FR-06
Widget accepts completedStepIds as controlled state.
Must
FR-07
Collapsible mode hides the step list, showing only the progress bar header.
Should
FR-08
”Dismiss” action hides the entire widget and calls onDismiss.
Should
FR-09
onStepClick callback fires when a step title is clicked (for navigation).
Should
FR-10
Completion animation plays when all steps are completed.
Could
FR-11
Progress bar fill animates smoothly using motion tokens.
Should
Non-Functional Requirements
ID
Requirement
Target
NFR-01
Widget renders with 10 steps in < 10ms.
React Profiler measurement.
NFR-02
Bundle size
< 4 KB gzipped (excluding ManagedChecklist deps).
NFR-03
Progress bar animation
Uses --motion-standard (160ms) for fill transitions.
NFR-04
Reduced-motion
Progress bar fill transition is instant under prefers-reduced-motion: reduce.
NFR-05
Dark mode
Full token-based dark mode support.
API/Interface Requirements
interface OnboardingStep {
id:string;
title:string;
description?:string;
icon?:ReactNode;
}
interface OnboardingProgressBarProps {
title?:string; // default "Get started"
steps:OnboardingStep[];
completedStepIds:string[];
onStateChange:(completedStepIds:string[])=>void;
onStepClick?:(stepId:string)=>void;
onDismiss?:()=>void;
collapsible?:boolean; // default true
defaultCollapsed?:boolean; // default false
completionMessage?:string; // default "All done!"
className?:string;
}
Accessibility Requirements
ID
Requirement
A11Y-01
Progress bar uses role="progressbar" with aria-valuenow, aria-valuemin=0, aria-valuemax=100.
A11Y-02
Step checkboxes are standard role="checkbox" with aria-checked.
A11Y-03
Collapse toggle has aria-expanded and aria-controls pointing to the step list.
A11Y-04
Completion state is announced via aria-live="polite" region.
Progress header: A card-like container with title, progress bar (div with bg-primary width set to completion percentage), and “X of Y completed” text.
Step list: Render steps as checkbox rows. Consider reusing ChecklistRow from checklist-foundation or building a simpler variant. Each row: checkbox + title + optional description.
State management: The widget is fully controlled. completedStepIds is the source of truth. On checkbox toggle, compute the new array and call onStateChange.
Collapsible: Use a simple useState for collapsed state with aria-expanded on the toggle button. Animate height via motion tokens.
Dismiss: An X button or “Dismiss” link calls onDismiss. The widget renders null after dismissal (consumer controls visibility).
Completion: When completedStepIds.length === steps.length, show a success state. Consider a brief animated checkmark using CSS keyframes.