Skip to content
Create account or Sign in
The Stripe Docs logo
/
Ask AI
Create accountSign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
APIs & SDKsHelp
Overview
Versioning
Changelog
Upgrade your API version
Upgrade your SDK version
Essentials
SDKs
API
Testing
Stripe CLI
Sample projects
Tools
Stripe Dashboard
Workbench
Developers Dashboard
Stripe Shell
Stripe for Visual Studio Code
Features
Workflows
Event Destinations
Stripe health alertsFile uploads
AI solutions
Agent toolkit
Model Context ProtocolBuild agentic AI SaaS Billing workflows
Security and privacy
Security
Stripebot web crawler
Privacy
Extend Stripe
Build Stripe apps
    Overview
    Get started
    Create an app
    How Stripe Apps work
    Sample apps
    Build an app
    Store secrets
    API authentication methods
    Authorisation flows
    Server-side logic
    Listen to events
    Handle different modes
    Enable sandbox support
    Enable local network access
    App settings page
    Build a UI
    Onboarding
    Distribute your app
    Distribution options
    Upload your app
    Versions and releases
    Test your app
    Publish your app
    Promote your app
    Add deep links
    Create install links
    Assign roles in UI extensions
    Post-install actions
    App analytics
    Embedded components
    Embed third-party Stripe Apps
    Migrating to Stripe Apps
    Migrate or build an extension
    Migrate a plugin to Stripe Apps or Stripe Connect
    Reference
    App manifest
    CLI
    Extension SDK
    Permissions
    Viewports
    Design patterns
    Components
      Accordion
      Badge
      Banner
      BarChart
      Box
      Button
      ButtonGroup
      Tickbox
      Chip
      ContextView
      DateField
      DetailPageModule
      DetailPagePropertyList
      DetailPageTable
      Divider
      FocusView
      FormFieldGroup
      Icon
      Img
      Inline
      LineChart
      Link
      List
      Menu
      OnboardingView
      PropertyList
      Radio
      Select
      SettingsView
      SignInView
      Sparkline
      Spinner
      Switch
      Table
      Tabs
      TaskList
      TextArea
      TextField
      Toast
      Tooltip
Use apps from Stripe
Partners
Partner ecosystem
Partner certification
United States
English (United Kingdom)
HomeDeveloper resourcesBuild Stripe appsComponents

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

PropertyType

children

Required

React.ReactNode

React component that renders the content of the primary column.

completed

Required

boolean

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.

tasks

Required

Array<Tasks>

A list of onboarding tasks.

Related types: Tasks.

title

Required

string

Onboarding step title.

description

Optional

string | undefined

Onboarding step description.

error

Optional

React.ReactNode

Information about an error that occurred during onboarding.

pending

Optional

boolean | undefined

Whether the onboarding flow is in a loading state. Shows spinner and loading message when true.

Tasks

PropertyType

title

Required

string

The display title of the task.

onPress

Optional

((event: PressEvent) => void) | undefined

An event handler for when the user clicks anywhere on the task.

status

Optional

("not-started" | "in-progress" | "blocked" | "complete") | undefined

The current status of the task.

subTasks

Optional

Array<SubTasks> | undefined

A list of sub-tasks that belong to this task.

Related types: SubTasks.

SubTasks

PropertyType

title

Required

string

The display title of the task.

onPress

Optional

((event: PressEvent) => void) | undefined

An event handler for when the user clicks anywhere on the task.

status

Optional

("not-started" | "in-progress" | "blocked" | "complete") | undefined

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.

Loading example...
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.

Loading example...
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> )

See also

  • Design patterns to follow
  • Style your app
  • UI testing
Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc