OnboardingView component for Stripe AppsPublic preview
Use OnboardingView to implement an onboarding flow of your Stripe App
To add the OnboardingView component to your app:
import {OnboardingView} from '@stripe/ui-extension-sdk/ui';
The OnboardingView component provides a standardised way to implement an onboarding view with a predefined structure:
- Left sidebar that renders a list of onboarding tasks
- Main content area that displays the content of a given onboarding step
The list of onboarding tasks is specified as an array of TaskListItemProps items. You can fully customise the content of the onboarding step itself by specifying a custom React view as a direct child of the <OnboardingView>. This approach lets you implement a custom onboarding step based on your business needs, while the Stripe Dashboard controls the way the list of onboarding tasks renders.
OnboardingView props
| Property | Type |
|---|---|
| Required
React component that renders the content of the primary column. |
| Required
Whether all onboarding tasks are done. When set to true, the onboarding modal window will automatically close after a brief delay to return the user to their previous location. |
| Required
A list of onboarding tasks. Related types: Tasks. |
| Required
Onboarding step title. |
| Optional
Onboarding step description. |
| Optional
Information about an error that occurred during onboarding. |
| Optional
Whether the onboarding flow is in a loading state. Shows spinner and loading message when true. |
Tasks
| Property | Type |
|---|---|
| Required
The display title of the task. |
| Optional
An event handler for when the user clicks anywhere on the task. |
| Optional
The current status of the task. |
| Optional
A list of sub-tasks that belong to this task. Related types: SubTasks. |
SubTasks
| Property | Type |
|---|---|
| Required
The display title of the task. |
| Optional
An event handler for when the user clicks anywhere on the task. |
| Optional
The current status of the task. |
Basic
The following example demonstrates the basic usage of the OnboardingView component, where a different React view is rendered for each onboarding step.
import React, {useState, useReducer, useCallback} from 'react'; import { FormFieldGroup, TextField, OnboardingView, Switch, TaskListItemProps, } from '@stripe/ui-extension-sdk/ui'; const onboardingTasks: Record<TaskName, TaskListItemProps> = { addInfo: { title: 'Add business info', status: 'in-progress', onPress: () => handlePress('addInfo'), }, connectBank: { title: 'Connect your bank', status: 'not-started', onPress: () => handlePress('connectBank'), }, review: { title: 'Review and finish', status: 'not-started', onPress: () => handlePress('review'), }, }; // These view implement the UI required by a particular onboarding step const steps: Record<TaskName, React.FunctionComponent> = { addInfo: () => ( <FormFieldGroup legend="Business Info" description="Add business info"> <TextField label="Company name" placeholder="Company name" hiddenElements={['label']} /> </FormFieldGroup> ), connectBank: () => ( <FormFieldGroup legend="Connect your bank" description="Enter the bank account to which withdrawals will be sent." > <TextField label="Bank name" placeholder="Bank name" hiddenElements={['label']} /> </FormFieldGroup> ), review: () => ( <FormFieldGroup legend="Specify settings" layout="vertical"> <Switch label="Enable automatic transfers" description="Enable automatic transfers" /> <Switch label="Enable auto-import of transactions" description="Enable auto-import of transactions" /> </FormFieldGroup> ), }; const handlePress = useCallback((taskName: TaskName) => { setTaskName(taskName); dispatch({type: 'TOGGLE_STATUS', taskName}); }, []); const [taskName, setTaskName] = useState<TaskName>('addInfo'); const [tasks, dispatch] = useReducer(taskReducer, onboardingTasks); const taskListItems = Object.values(tasks); const title = tasks[taskName].title; const description = `Please complete the onboarding step.`; const completed = taskListItems.every((item) => item.status === 'complete'); const OnboardingViewContent = steps[taskName]; return ( <OnboardingView title={title} description={description} completed={completed} tasks={taskListItems} > <OnboardingViewContent /> </OnboardingView> ); function getNextStatus( status: string, ): 'not-started' | 'in-progress' | 'complete' { switch (status) { case 'complete': return 'not-started'; case 'not-started': return 'in-progress'; case 'in-progress': return 'complete'; default: return 'not-started'; } } type TaskName = 'addInfo' | 'connectBank' | 'review'; type TaskAction = { type: 'TOGGLE_STATUS'; taskName: TaskName; }; // Reducer function to handle state updates function taskReducer( state: Record<TaskName, TaskListItemProps>, action: TaskAction, ): Record<TaskName, TaskListItemProps> { switch (action.type) { case 'TOGGLE_STATUS': return { ...state, [action.taskName]: { ...state[action.taskName], status: getNextStatus(state[action.taskName].status as string), }, }; default: return state; } }
Transitional
This example demonstrates how to use the error and pending props to handle different states during the onboarding flow.
The component manages three distinct states:
- Pending: Shows a loading spinner while fetching onboarding data
- Error: Displays a Try again button if the fetch fails
- Ready: Renders the normal onboarding experience with tasks and forms
When the example component first loads, it simulates a failed fetch to demonstrate the error state. When you click Try again, the fetch succeeds and displays the actual onboarding content. This approach allows you to handle loading and error scenarios smoothly without requiring additional components or complex state management.
import React, {useCallback, useEffect, useState} from 'react'; import { FormFieldGroup, TextField, Button, OnboardingView, TaskListItemProps, } from '@stripe/ui-extension-sdk/ui'; type OnboardingData = { state: 'pending' | 'error' | 'ready'; tasks: TaskListItemProps[]; }; const [onboarding, setOnboarding] = useState<OnboardingData>({ state: 'pending', tasks: [], }); const fetchTasks = useCallback( (() => { let isFirstTry = true; return () => { setOnboarding({state: 'pending', tasks: []}); setTimeout(() => { if (isFirstTry) { isFirstTry = false; setOnboarding((prev) => ({...prev, state: 'error'})); } else { setOnboarding({ state: 'ready', tasks: [ {title: 'Add business info', status: 'in-progress'}, {title: 'Connect your bank', status: 'not-started'}, {title: 'Review and finish', status: 'not-started'}, ], }); } }, 2000); }; })(), [], ); useEffect(fetchTasks, [fetchTasks]); const error = onboarding.state === 'error' ? ( <Button onPress={fetchTasks}>Try again!</Button> ) : null; const pending = onboarding.state === 'pending'; return ( <OnboardingView error={error} pending={pending} title="Onboarding title" description="Onboarding description" completed={false} tasks={onboarding.tasks} > <FormFieldGroup legend="Business Info" description="Add business info!"> <TextField label="Company name" placeholder="Company name" hiddenElements={['label']} /> </FormFieldGroup> </OnboardingView> )