Onboarding
A few steps in a dialog, with a scene that morphs between them and confetti at the end.
Onboarding is a short tour in a dialog: a scene that morphs between steps, text that crossfades in place, page dots, Back and Next, and confetti once it's finished. Use Onboarding the first time someone opens an app or a feature, for three to five steps at most.
How a tour works
Steps
Each of the
stepshas atitle, which names the dialog while it shows, abodyof a line or two and a scene inmedia, drawn 384×200.Shared pieces
Onboarding.Sharedmarks a piece of a scene that carries over: a piece with the sameidin the next step's scene is the same piece, moved.The first visit
With a
storageKey, the tour opens by itself the first time and, once it's finished or closed, never again.The last step
The last step's button finishes the tour, and
onFinishruns as the confetti flies.
The dialog keeps its size as the steps change, and Next and Back carry forward and back arrows.
Reduced motion. The scene and the text change at once, and nothing celebrates.
Onboarding
When to use it
Use it for
- Showing a new app's three to five main ideas the first time it opens
- A short tour someone can open again from a Help button
Not for
- A single message: use Dialog
- A task with inputs and steps: use a page or a form
- Tips while working: use a Tooltip or a Callout
Examples
First run tour
A tour with a storageKey opens by itself until it's finished or closed; Start the app mounts it afresh, and Forget clears what it remembered.
Not seen yet, so it opens on the next start
Help tour
A tour kept open in state, so someone can open it again from a Help button.
Welcome screen
An empty library's first screen: Take the tour opens the steps, and finishing them changes what the screen says.
No decks yet
Take a short tour first, or start a deck right away.
Variants and states
Three steps
The slide carries over between steps on spring.smooth while the background crossfades; the text crossfades in place; Done sends up confetti.
Props
Onboarding
| Prop | Type | Default | Description |
|---|---|---|---|
stepsrequired | readonly OnboardingStep[] | The steps, in order. | |
open | boolean | Whether it's open. Pair with onOpenChange to control it. | |
defaultOpen | boolean | false | Whether it starts open when uncontrolled. Defaults to false, or to true the first time with a storageKey. |
onOpenChange | ((open: boolean) => void) | Called when it opens or closes. | |
storageKey | string | Remembers in local storage that it was finished or closed, under this key. With one, it opens by itself the first time and never again. | |
onFinish | (() => void) | Called when the last step's button finishes it, as the confetti flies. | |
labels | Partial<OnboardingLabels> | Words to use instead of the English ones. | |
ref | Ref<HTMLDivElement> | The onboarding's content inside the dialog. | |
className | string | Extra classes for the onboarding's content. |
Onboarding.Shared
| Prop | Type | Default | Description |
|---|---|---|---|
idrequired | string | Names the piece across steps: a piece with the same id in the next step's scene is the same piece, moved. | |
rotate | number | 0 | How far the piece is turned in this step, in degrees. Defaults to 0. |
scale | number | 1 | How big the piece is in this step, as a scale. Defaults to 1. |
It also takes MotionElementProps<"div">.
OnboardingStep
One step of an onboarding.
| Field | Type | Default | Description |
|---|---|---|---|
titlerequired | string | The step's title. While the step shows, it names the dialog. | |
bodyrequired | ReactNode | A line or two about the step. | |
caption | ReactNode | A short note under the body, such as a keyboard tip. | |
mediarequired | ReactNode | The step's scene, drawn 384×200. Pieces that carry over to the next step go in Onboarding.Shared. | |
background | string | The scene's background, such as a palette gradient. It crossfades between steps. |
OnboardingLabels
The words an `Onboarding` uses, for other languages.
| Field | Type | Default | Description |
|---|---|---|---|
backrequired | string | The button that goes back a step. | |
nextrequired | string | The button that goes on to the next step. | |
finishrequired | string | The forward button's label on the last step, which finishes. | |
closerequired | string | Names the close button. | |
steprequired | (step: number, count: number) => string | Says which step shows, for the page dots and as each step arrives. |
Also exported
| Export | Description |
|---|---|
hasSeenOnboarding(storageKey: string): boolean | Whether an onboarding with this storageKey was finished or closed before, for an app that controls when
it opens: open it at first only when this is false. |
Accessibility
A modal dialog named by the current step's title and described by its body. As a step arrives a polite live region says "Step 2 of 4" and its title. Back is quiet but still focusable on the first step; left and right arrows move between steps outside text fields; the finish button's label changes inside the same button, so focus stays on it. The page dots are one image naming the step. With reduced motion the scenes and text fade in 100ms and the confetti stays off.
| Keys | What they do |
|---|---|
| Right arrow | Goes to the next step, unless focus is in a text field |
| Left arrow | Goes back a step, unless focus is in a text field |
| Enter or Space | Presses Back or the forward button, which starts focused; on the last step it finishes with confetti and closes the dialog |
| Escape | Closes it, remembered under its storageKey, and puts focus back on what opened it |
| Tab or Shift+Tab | Moves between Back, the forward button and the close button, staying inside the dialog |
Motion
It changes shape as one surface, on `spring.smooth`, or `spring.morph` for a big change, rather than closing and reopening.
With reduced motion: The dialog, its scenes and its text fade in 100ms, shared pieces and the page dots take their new places at once, and the confetti stays off, so the last step closes the dialog without waiting for it.
Layout
It's a 400px dialog (--bt-w-dialog), never wider than the window less 16px a side: a 384 by 200 scene inset 8px at the top, which keeps its shape as the window narrows, then the title, body and caption, the page dots, and Back and the forward button in two equal columns 48px tall (--bt-h-cta). The text wraps and the dialog's height follows it from step to step, and the forward button keeps its width when Next becomes Done.
Related
See it in the Deckhand demo.
Related
- Dialog
A modal dialog that dims the page, traps focus and hands it back when it closes.
- PageDots
A row of dots showing which step of a few is current, the current one a pill that moves on spring.snappy.
- Confetti
A short burst of confetti from an element, for a genuine finish such as completing onboarding.
- Principles
The ten rules every buttery animation follows, and the few things it never animates.