OnboardingPortal
A full-screen, multi-step onboarding wizard that guides new accounts through business setup, phone number configuration, and hardware assignment.
Basic Usage
import { DialstackComponentsProvider } from '@dialstack/sdk';
import { OnboardingPortal } from '@dialstack/sdk/react/onboarding';
function OnboardingPage({ dialstack, clientSecret }) {
return (
<DialstackComponentsProvider dialstack={dialstack} clientSecret={clientSecret}>
<OnboardingPortal />
</DialstackComponentsProvider>
);
}
The OnboardingPortal is imported from @dialstack/sdk/react/onboarding, not from the main @dialstack/sdk entry point. This keeps the onboarding bundle separate from the lighter-weight components.
The portal automatically saves onboarding progress to the server. Users can leave and return at any time — the wizard resumes where they left off.
How It Works
The onboarding portal presents three main steps, each with its own substeps:
| Step | Description | Substeps |
|---|---|---|
| Account | Business profile and team setup | Business Details, Team Members |
| Numbers | Phone number ordering and porting | Number options, ordering/porting flow, primary number, caller ID, directory listing |
| Hardware | Device assignment for team members | Device Assignment |
The portal has three view modes that users progress through:
- Splash screen — a welcome screen shown on first visit
- Overview — a dashboard showing progress across all steps with status indicators
- Wizard — the step-by-step form workflow
When all steps are complete, a celebration screen is shown. After that, the overview screen serves as the landing page where users can review or revise any step.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
locale | Locale | English | Custom locale for UI strings |
formatting | FormattingOptions | - | Date/phone formatting options |
icons | ComponentIcons | - | Custom SVG icons |
collectionOptions | OnboardingCollectionOptions | - | Control which steps to show |
theme | 'light' | 'dark' | 'light' | Color theme |
appearance | { variables?: { colorPrimary?: string; colorPrimaryHover?: string } } | - | Brand color overrides |
logoHtml | string | - | HTML string for sidebar logo |
platformName | string | - | Platform name shown in the UI |
onBack | () => void | - | Back button callback (shows button when provided) |
backLabel | string | - | Label for the back button |
fullTermsOfServiceUrl | string | - | Link to full terms of service |
recipientTermsOfServiceUrl | string | - | Link to recipient terms of service |
privacyPolicyUrl | string | - | Link to privacy policy |
documentationUrl | string | - | Link shown on the overview screen |
onScheduleCall | () => void | - | Callback for "Schedule a Call" on the overview screen |
onHelpSupport | () => void | - | Callback for "Help & Support" in the sidebar |
onStepChange | (event: { step: AccountOnboardingStep }) => void | - | Called when the active step changes |
className | string | - | Additional CSS class for the root element |
style | React.CSSProperties | - | Inline styles for the root element |
Controlling Steps
Use collectionOptions to show or hide specific steps. The final completion screen is always shown regardless of these options.
Show only specific steps
<OnboardingPortal
collectionOptions={{
steps: {
include: ['account', 'numbers'],
},
}}
/>
Exclude specific steps
<OnboardingPortal
collectionOptions={{
steps: {
exclude: ['hardware'],
},
}}
/>
OnboardingCollectionOptions
| Option | Type | Description |
|---|---|---|
steps.include | AccountOnboardingStep[] | Show only these steps |
steps.exclude | AccountOnboardingStep[] | Hide these steps |
When both include and exclude are set, include is applied first, then exclude removes from that result.
AccountOnboardingStep
The available step values are:
| Value | Description |
|---|---|
'account' | Business details and team members |
'numbers' | Phone number ordering, porting, and configuration |
'hardware' | Device assignment |
'final_complete' | Completion screen (always shown) |
White-Labeling
Customize the portal's branding to match your platform:
<OnboardingPortal
platformName="Acme Telecom"
logoHtml={`
<div style="display:flex;align-items:center;gap:8px">
<img src="/logo.svg" width="28" height="24" alt="" />
<span style="font-size:20px;font-weight:700;color:#f0f0ff">
Acme Telecom
</span>
</div>
`}
appearance={{
variables: {
colorPrimary: '#00A67E',
colorPrimaryHover: '#008F6D',
},
}}
/>
The appearance.variables colors are applied to the sidebar, buttons, and accent elements throughout the wizard. When not provided, the portal uses the colors set via initialize().
Dark Theme
<OnboardingPortal theme="dark" />
The theme can also be set globally via the appearance.theme option in initialize(). The component-level theme prop takes precedence.
Navigation Callbacks
onBack
Provide an onBack callback to show a back button in the sidebar. Use this to let users navigate back to your application:
<OnboardingPortal onBack={() => router.push('/dashboard')} backLabel="Back to Dashboard" />
onStepChange
Track which step the user is on:
<OnboardingPortal
onStepChange={(event) => {
analytics.track('onboarding_step', { step: event.step });
}}
/>
Help and Support
The overview screen and sidebar can link to help resources:
<OnboardingPortal
documentationUrl="https://docs.example.com/onboarding"
onScheduleCall={() => {
window.open('https://calendly.com/example/onboarding', '_blank');
}}
onHelpSupport={() => {
window.Intercom('showNewMessage', 'I need help with onboarding');
}}
/>
documentationUrl— shows a "View Documentation" link on the overview screenonScheduleCall— shows a "Schedule a Call" button on the overview screenonHelpSupport— shows a "Help & Support" link in the sidebar
Legal Links
Display terms and privacy links on the completion screen:
<OnboardingPortal
fullTermsOfServiceUrl="https://example.com/terms"
recipientTermsOfServiceUrl="https://example.com/recipient-terms"
privacyPolicyUrl="https://example.com/privacy"
/>
Complete Example
import { initialize, DialstackComponentsProvider } from '@dialstack/sdk';
import { OnboardingPortal } from '@dialstack/sdk/react/onboarding';
import { useEffect, useState } from 'react';
const dialstack = initialize({
publishableKey: 'pk_live_YOUR_KEY',
appearance: {
theme: 'light',
},
});
function OnboardingApp() {
const [clientSecret, setClientSecret] = useState<string | null>(null);
useEffect(() => {
fetch('/api/dialstack/session', { method: 'POST' })
.then((res) => res.json())
.then((data) => setClientSecret(data.client_secret));
}, []);
if (!clientSecret) return <div>Loading...</div>;
return (
<DialstackComponentsProvider dialstack={dialstack} clientSecret={clientSecret}>
<OnboardingPortal
platformName="Acme Telecom"
logoHtml={`
<div style="display:flex;align-items:center;gap:8px">
<img src="/logo.svg" width="28" height="24" alt="" />
<span style="font-size:20px;font-weight:700;color:#f0f0ff">
Acme Telecom
</span>
</div>
`}
appearance={{
variables: {
colorPrimary: '#6772E5',
colorPrimaryHover: '#5469D4',
},
}}
collectionOptions={{
steps: { exclude: ['hardware'] },
}}
onBack={() => (window.location.href = '/dashboard')}
backLabel="Back to Dashboard"
documentationUrl="https://docs.example.com/setup"
onScheduleCall={() => window.open('https://calendly.com/example')}
onHelpSupport={() => window.Intercom?.('show')}
onStepChange={(event) => {
console.log('Step changed:', event.step);
}}
fullTermsOfServiceUrl="https://example.com/terms"
privacyPolicyUrl="https://example.com/privacy"
/>
</DialstackComponentsProvider>
);
}
Next Steps
- DialstackComponentsProvider - Provider configuration
- Theming - Global appearance customization
- i18n - Internationalization