Onboarding
A step-by-step flow with a segmented progress bar and CSS-only step transitions
Step 1
A short description of step 1.
Installation
pnpm dlx shadcn@latest add @alexandrejoly/onboardingUsage
import { Onboarding, OnboardingContent, OnboardingDescription, OnboardingFooter, OnboardingHeader, OnboardingIndicator, OnboardingNav, OnboardingNextButton, OnboardingPrevButton, OnboardingStep, OnboardingTitle,} from "@/components/ui/onboarding";<Onboarding onComplete={() => setOpen(false)} totalSteps={2}> <OnboardingContent> <OnboardingStep value={1}> <OnboardingHeader> <OnboardingTitle>Step 1</OnboardingTitle> <OnboardingDescription>A short description of step 1.</OnboardingDescription> </OnboardingHeader> </OnboardingStep> <OnboardingStep value={2}> <OnboardingHeader> <OnboardingTitle>Step 2</OnboardingTitle> <OnboardingDescription>A short description of step 2.</OnboardingDescription> </OnboardingHeader> </OnboardingStep> </OnboardingContent> <OnboardingFooter> <OnboardingIndicator /> <OnboardingNav> <OnboardingPrevButton /> <OnboardingNextButton /> </OnboardingNav> </OnboardingFooter></Onboarding>Examples
useOnboarding
useOnboarding drives custom controls: a step counter, then a skip button that completes the flow and turns into a restart on the last step.
Step 1 of 3
Step 1
A short description of step 1.
Transition
The text slides in from the right on Continue and from the left on Previous, while the media crossfades. The steps share one grid cell, so the leaving step fades out as the next fades in. Classes alone run it: data-starting-style and data-ending-style set where a step starts and ends, and data-direction picks the side. With reduced motion, the text fades without sliding.
Step 1
A short description of step 1.
Accessibility
OnboardingIndicator is one progressbar read as “Step 2 of 3”; its segments are hidden from assistive tech, so nobody hears one bar per step.
Focus stays on the button that changed the step, and the new step is not announced. When a step carries content people must hear, move focus to its OnboardingTitle, given tabIndex={-1}, once the step renders.
A step you leave is inert while it animates out, so focus and screen readers reach only the current step.
Meets WCAG 2.2: 2.4.3 Focus Order (opens in a new tab) · 4.1.2 Name, Role, Value (opens in a new tab)
API reference
Onboarding
Holds the current step. After the first move, data-direction reads next or previous.
Takes every prop of div.
| Prop | Type | Default |
|---|---|---|
defaultValueThe step to start on, counted from 1. Default: | number | 1 |
onCompleteCalled when | () => void | None |
totalStepsHow many steps there are. Known on the first render, so the server draws the right indicator and button. | number | None |
OnboardingStep
One step, rendered while it is the current one. The step you leave stays, with data-ending-style, until its transitions and animations end; the step you reach has data-starting-style for one frame, or turns back from where it is if it was still leaving. Both carry data-direction, next or previous. With no transition, the steps swap at once.
Takes every prop of div.
| Prop | Type |
|---|---|
valueIts position, counted from 1. | number |
OnboardingMedia
Centers an image or illustration and takes the height of what you put in it.
Takes every prop of div.
OnboardingIndicator
One progressbar announced as “Step 2 of 3”, drawn as one shadcn Progress per step, hidden from assistive tech. Its name defaults to “Onboarding progress”; pass aria-label to change it.
Takes every prop of div.
OnboardingPrevButton
Ghost button to the previous step, disabled on the first. It stays focusable while disabled, so focus is not lost when it brings the flow back to step 1. An onClick runs before the step changes.
Takes every prop of shadcn Button (opens in a new tab).
| Prop | Type | Default |
|---|---|---|
childrenThe label. Default: | ReactNode | "Previous" |
OnboardingNextButton
Moves forward, or calls onComplete on the last step. An onClick runs before the step changes.
Takes every prop of shadcn Button (opens in a new tab).
| Prop | Type | Default |
|---|---|---|
childrenThe label. Default: | ReactNode | "Continue" |
lastLabelThe label on the last step. Default: | ReactNode | "Got it" |
useOnboarding()
Reads and drives the flow from any descendant of Onboarding. setStep throws outside 1 to totalSteps.
| Return value | Type |
|---|---|
currentStep, totalStepsThe current step and the step count. | number |
canGoToNextStep, canGoToPrevStepWhether a step exists after or before the current one. | boolean |
goToNextStep, goToPrevStep, resetMove one step, or back to the first. | () => void |
setStepJump to a step. | Dispatch< |