Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
import { Onboarding, useOnboarding } from '@/components/ui/onboarding';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
export const OnboardingPresets = {
welcome: [
{
id: 'welcome',
title: 'Welcome to Our App',
description:
'Discover amazing features and get started with your journey.',
icon: <Text style={{ fontSize: 80 }}>👋</Text>,
},
{
id: 'features',
title: 'Powerful Features',
description:
'Experience cutting-edge functionality designed to make your life easier.',
icon: <Text style={{ fontSize: 80 }}>⚡</Text>,
},
{
id: 'personalize',
title: 'Personalize Your Experience',
description: 'Customize the app to match your preferences and workflow.',
icon: <Text style={{ fontSize: 80 }}>🎨</Text>,
},
{
id: 'ready',
title: "You're All Set!",
description:
"Everything is ready. Let's start exploring what you can achieve.",
icon: <Text style={{ fontSize: 80 }}>🚀</Text>,
},
],
features: [
{
id: 'organize',
title: 'Stay Organized',
description: 'Keep all your important information in one secure place.',
icon: <Text style={{ fontSize: 80 }}>📋</Text>,
},
{
id: 'collaborate',
title: 'Collaborate Seamlessly',
description: 'Work together with your team in real-time, anywhere.',
icon: <Text style={{ fontSize: 80 }}>🤝</Text>,
},
{
id: 'automate',
title: 'Automate Your Workflow',
description: 'Set up smart automations to save time and reduce errors.',
icon: <Text style={{ fontSize: 80 }}>🤖</Text>,
},
],
security: [
{
id: 'secure',
title: 'Your Data is Secure',
description:
'We use end-to-end encryption to keep your information safe.',
icon: <Text style={{ fontSize: 80 }}>🔒</Text>,
},
{
id: 'privacy',
title: 'Privacy First',
description: 'We never share your personal data with third parties.',
icon: <Text style={{ fontSize: 80 }}>🛡️</Text>,
},
{
id: 'control',
title: "You're in Control",
description: 'Manage your privacy settings and data preferences anytime.',
icon: <Text style={{ fontSize: 80 }}>⚙️</Text>,
},
],
};
export function OnboardingDemo() {
const { hasCompletedOnboarding, completeOnboarding, skipOnboarding } =
useOnboarding();
if (hasCompletedOnboarding) {
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 24,
}}
>
<Text variant='title'>Welcome Back!</Text>
<Text variant='body'>You've already completed the onboarding.</Text>
</View>
);
}
return (
<Onboarding
steps={OnboardingPresets.welcome}
onComplete={completeOnboarding}
onSkip={skipOnboarding}
showSkip={true}
showProgress={true}
swipeEnabled={true}
primaryButtonText='Get Started'
skipButtonText='Skip'
nextButtonText='Next'
backButtonText='Back'
/>
);
}
Installation
pnpm dlx bna-ui add onboarding
Usage
import { Onboarding, OnboardingStep } from '@/components/ui/onboarding';
const steps: OnboardingStep[] = [
{
id: '1',
title: 'Welcome',
description: 'Get started with our amazing app',
icon: <WelcomeIcon />,
},
{
id: '2',
title: 'Explore Features',
description: 'Discover all the powerful features we offer',
icon: <FeaturesIcon />,
},
{
id: '3',
title: 'Get Started',
description: "You are all set! Let's begin your journey",
icon: <StartIcon />,
},
];
<Onboarding
steps={steps}
onComplete={() => console.log('Onboarding completed')}
onSkip={() => console.log('Onboarding skipped')}
/>;
Examples
Default
import { Onboarding, useOnboarding } from '@/components/ui/onboarding';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
export const OnboardingPresets = {
welcome: [
{
id: 'welcome',
title: 'Welcome to Our App',
description:
'Discover amazing features and get started with your journey.',
icon: <Text style={{ fontSize: 80 }}>👋</Text>,
},
{
id: 'features',
title: 'Powerful Features',
description:
'Experience cutting-edge functionality designed to make your life easier.',
icon: <Text style={{ fontSize: 80 }}>⚡</Text>,
},
{
id: 'personalize',
title: 'Personalize Your Experience',
description: 'Customize the app to match your preferences and workflow.',
icon: <Text style={{ fontSize: 80 }}>🎨</Text>,
},
{
id: 'ready',
title: "You're All Set!",
description:
"Everything is ready. Let's start exploring what you can achieve.",
icon: <Text style={{ fontSize: 80 }}>🚀</Text>,
},
],
features: [
{
id: 'organize',
title: 'Stay Organized',
description: 'Keep all your important information in one secure place.',
icon: <Text style={{ fontSize: 80 }}>📋</Text>,
},
{
id: 'collaborate',
title: 'Collaborate Seamlessly',
description: 'Work together with your team in real-time, anywhere.',
icon: <Text style={{ fontSize: 80 }}>🤝</Text>,
},
{
id: 'automate',
title: 'Automate Your Workflow',
description: 'Set up smart automations to save time and reduce errors.',
icon: <Text style={{ fontSize: 80 }}>🤖</Text>,
},
],
security: [
{
id: 'secure',
title: 'Your Data is Secure',
description:
'We use end-to-end encryption to keep your information safe.',
icon: <Text style={{ fontSize: 80 }}>🔒</Text>,
},
{
id: 'privacy',
title: 'Privacy First',
description: 'We never share your personal data with third parties.',
icon: <Text style={{ fontSize: 80 }}>🛡️</Text>,
},
{
id: 'control',
title: "You're in Control",
description: 'Manage your privacy settings and data preferences anytime.',
icon: <Text style={{ fontSize: 80 }}>⚙️</Text>,
},
],
};
export function OnboardingDemo() {
const { hasCompletedOnboarding, completeOnboarding, skipOnboarding } =
useOnboarding();
if (hasCompletedOnboarding) {
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 24,
}}
>
<Text variant='title'>Welcome Back!</Text>
<Text variant='body'>You've already completed the onboarding.</Text>
</View>
);
}
return (
<Onboarding
steps={OnboardingPresets.welcome}
onComplete={completeOnboarding}
onSkip={skipOnboarding}
showSkip={true}
showProgress={true}
swipeEnabled={true}
primaryButtonText='Get Started'
skipButtonText='Skip'
nextButtonText='Next'
backButtonText='Back'
/>
);
}
With Images
import { Image } from '@/components/ui/image';
import { Onboarding, OnboardingStep } from '@/components/ui/onboarding';
import React from 'react';
const WelcomeImage = () => (
<Image
source={{
uri: 'https://images.unsplash.com/photo-1637858868799-7f26a0640eb6?q=80&w=2960&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
}}
width={300}
aspectRatio={1}
variant='circle'
/>
);
const FeaturesImage = () => (
<Image
source={{
uri: 'https://images.unsplash.com/photo-1644190022446-04b99df7259a?q=80&w=2012&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
}}
width={300}
aspectRatio={1}
/>
);
const StartImage = () => (
<Image
source={{
uri: 'https://images.unsplash.com/photo-1575737698350-52e966f924d4?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
}}
width={420}
aspectRatio={9 / 14}
/>
);
export function OnboardingImages() {
const steps: OnboardingStep[] = [
{
id: '1',
title: 'Welcome to the Team',
description:
'Join thousands of users who have already discovered the power of our platform.',
image: <WelcomeImage />,
},
{
id: '2',
title: 'Powerful Features',
description:
'Access advanced tools and features that will help you achieve your goals faster.',
image: <FeaturesImage />,
},
{
id: '3',
title: 'Ready to Launch',
description:
"Everything is set up and ready. Let's start building something amazing together!",
image: <StartImage />,
},
];
return (
<Onboarding
steps={steps}
onComplete={() => console.log('Onboarding with images completed!')}
onSkip={() => console.log('Onboarding with images skipped!')}
primaryButtonText="Let's Go"
nextButtonText='Continue'
/>
);
}
Custom Styling
import { Onboarding, OnboardingStep } from '@/components/ui/onboarding';
import { Feather } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import React from 'react';
const GradientIcon = ({
iconName,
colors,
}: {
iconName: string;
colors: [string, string];
}) => (
<LinearGradient
colors={colors}
style={{
padding: 24,
borderRadius: 70,
alignItems: 'center',
justifyContent: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.15,
shadowRadius: 12,
elevation: 6,
}}
>
<Feather name={iconName as any} size={64} color='white' />
</LinearGradient>
);
export function OnboardingStyled() {
const steps: OnboardingStep[] = [
{
id: '1',
title: 'Secure & Private',
description:
'Your data is protected with end-to-end encryption. We prioritize your privacy above all else.',
icon: <GradientIcon iconName='shield' colors={['#667eea', '#764ba2']} />,
backgroundColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
},
{
id: '2',
title: 'Lightning Fast',
description:
'Experience blazing fast performance with our optimized infrastructure and smart caching.',
icon: <GradientIcon iconName='zap' colors={['#f093fb', '#f5576c']} />,
backgroundColor: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
},
{
id: '3',
title: 'Always Connected',
description:
'Stay connected with real-time sync across all your devices. Never miss an important update.',
icon: <GradientIcon iconName='wifi' colors={['#4facfe', '#00f2fe']} />,
backgroundColor: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
},
];
return (
<Onboarding
steps={steps}
onComplete={() => console.log('Styled onboarding completed!')}
onSkip={() => console.log('Styled onboarding skipped!')}
primaryButtonText='Start Now'
nextButtonText='Next Step'
skipButtonText='Skip Intro'
style={{ backgroundColor: '#1a1a2e' }}
/>
);
}
No Skip Button
import { Onboarding, OnboardingStep } from '@/components/ui/onboarding';
import { Feather } from '@expo/vector-icons';
import React from 'react';
import { View } from 'react-native';
const InfoIcon = ({ name, color }: { name: string; color: string }) => (
<View
style={{
padding: 20,
backgroundColor: `${color}20`,
borderRadius: 60,
borderWidth: 2,
borderColor: color,
}}
>
<Feather name={name as any} size={60} color={color} />
</View>
);
export function OnboardingNoSkip() {
const steps: OnboardingStep[] = [
{
id: '1',
title: 'Setup Your Profile',
description:
"Let's start by setting up your profile. This helps us personalize your experience.",
icon: <InfoIcon name='user' color='#8b5cf6' />,
},
{
id: '2',
title: 'Choose Preferences',
description:
'Select your preferences to customize the app according to your needs and workflow.',
icon: <InfoIcon name='settings' color='#06b6d4' />,
},
{
id: '3',
title: 'Enable Notifications',
description:
'Stay updated with important notifications. You can always change these settings later.',
icon: <InfoIcon name='bell' color='#f59e0b' />,
},
{
id: '4',
title: 'All Set!',
description:
"Congratulations! Your account is now ready. Let's dive in and explore the features.",
icon: <InfoIcon name='check-circle' color='#10b981' />,
},
];
return (
<Onboarding
steps={steps}
onComplete={() => console.log('Required onboarding completed!')}
showSkip={false}
primaryButtonText='Complete Setup'
nextButtonText='Continue'
backButtonText='Previous'
/>
);
}
Swipe Disabled
import { Onboarding, OnboardingStep } from '@/components/ui/onboarding';
import { Feather } from '@expo/vector-icons';
import React from 'react';
import { View } from 'react-native';
const StepIcon = ({
name,
bgColor,
iconColor,
}: {
name: string;
bgColor: string;
iconColor: string;
}) => (
<View
style={{
padding: 18,
backgroundColor: bgColor,
borderRadius: 50,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 3,
}}
>
<Feather name={name as any} size={56} color={iconColor} />
</View>
);
export function OnboardingNoSwipe() {
const steps: OnboardingStep[] = [
{
id: '1',
title: 'Tutorial Mode',
description:
'Follow along with our step-by-step tutorial. Use the buttons below to navigate at your own pace.',
icon: <StepIcon name='book-open' bgColor='#ede9fe' iconColor='#7c3aed' />,
},
{
id: '2',
title: 'Learn the Basics',
description:
'Master the fundamental features that will help you get the most out of our platform.',
icon: <StepIcon name='layers' bgColor='#dcfce7' iconColor='#16a34a' />,
},
{
id: '3',
title: 'Practice Makes Perfect',
description:
'Try out the features yourself in a safe environment before working with real data.',
icon: <StepIcon name='target' bgColor='#fef3c7' iconColor='#d97706' />,
},
];
return (
<Onboarding
steps={steps}
onComplete={() => console.log('Tutorial completed!')}
onSkip={() => console.log('Tutorial skipped!')}
swipeEnabled={false}
showProgress={true}
primaryButtonText='Start Using App'
nextButtonText='Next Lesson'
skipButtonText='Skip Tutorial'
/>
);
}
Custom Buttons
import { Onboarding, OnboardingStep } from '@/components/ui/onboarding';
import { Heart, Rocket, Target } from 'lucide-react-native';
import React from 'react';
export function OnboardingCustomButtons() {
const steps: OnboardingStep[] = [
{
id: '1',
title: '🎉 Welcome Aboard!',
description:
"We're thrilled to have you join our community of innovators and creators.",
icon: <Heart color='#ee5a52' size={100} />,
},
{
id: '2',
title: '🚀 Boost Your Productivity',
description:
'Discover powerful tools that will transform the way you work and collaborate.',
icon: <Rocket color='#4ecdc4' size={100} />,
},
{
id: '3',
title: '🎯 Achieve Your Goals',
description:
'Set ambitious targets and track your progress with our advanced analytics.',
icon: <Target color='#45b7d1' size={100} />,
},
];
return (
<Onboarding
steps={steps}
onComplete={() => console.log('Custom buttons onboarding completed!')}
onSkip={() => console.log('Custom buttons onboarding skipped!')}
primaryButtonText='🚀 Launch App'
nextButtonText='👉 Continue'
backButtonText='👈 Back'
skipButtonText='⏭️ Skip for Now'
/>
);
}
With Hook
import { Button } from '@/components/ui/button';
import {
Onboarding,
OnboardingStep,
useOnboarding,
} from '@/components/ui/onboarding';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React from 'react';
function MainApp() {
const { resetOnboarding } = useOnboarding();
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: '#f8fafc',
}}
>
<View style={{ alignItems: 'center', marginBottom: 40 }}>
{/* <Text>{}</Text> */}
<Text variant='heading' style={{ marginTop: 20, textAlign: 'center' }}>
Welcome to the App!
</Text>
<Text
variant='body'
style={{
marginTop: 12,
textAlign: 'center',
color: '#64748b',
lineHeight: 22,
}}
>
You've successfully completed the onboarding process. You can restart
it anytime using the button below.
</Text>
</View>
<Button
onPress={resetOnboarding}
variant='outline'
style={{ paddingHorizontal: 24 }}
>
🔄 Restart Onboarding
</Button>
</View>
);
}
function OnboardingFlow() {
const { completeOnboarding, skipOnboarding } = useOnboarding();
const steps: OnboardingStep[] = [
{
id: '1',
title: 'Hook-based State',
description:
'This onboarding uses the useOnboarding hook to manage state across your entire app.',
// icon: '🪝',
},
{
id: '2',
title: 'Persistent State',
description:
'The hook remembers your progress and can be used to control onboarding flow throughout your app.',
// icon: '📱',
},
{
id: '3',
title: 'Easy Integration',
description:
'Integrate onboarding state with your existing app navigation and user management.',
// icon: '🚀',
},
];
return (
<Onboarding
steps={steps}
onComplete={completeOnboarding}
onSkip={skipOnboarding}
primaryButtonText='Complete & Continue'
nextButtonText='Next Step'
skipButtonText='Skip Demo'
/>
);
}
export function OnboardingHook() {
const { hasCompletedOnboarding } = useOnboarding();
return hasCompletedOnboarding ? <MainApp /> : <OnboardingFlow />;
}
API Reference
Onboarding
The main onboarding component that manages the multi-step flow.
Prop | Type | Default | Description |
---|---|---|---|
steps | OnboardingStep[] | - | Array of onboarding steps to display. |
onComplete | () => void | - | Callback when onboarding is completed. |
onSkip | () => void | - | Callback when onboarding is skipped. |
showSkip | boolean | true | Whether to show the skip button. |
showProgress | boolean | true | Whether to show progress dots. |
swipeEnabled | boolean | true | Whether to enable swipe gestures. |
primaryButtonText | string | "Get Started" | Text for the primary button on the last step. |
skipButtonText | string | "Skip" | Text for the skip button. |
nextButtonText | string | "Next" | Text for the next button. |
backButtonText | string | "Back" | Text for the back button. |
style | ViewStyle | - | Additional styles for the container. |
children | ReactNode | - | Custom content to render in each step. |
OnboardingStep
Configuration object for each step in the onboarding flow.
Prop | Type | Default | Description |
---|---|---|---|
id | string | - | Unique identifier for the step. |
title | string | - | Title text for the step. |
description | string | - | Description text for the step. |
image | ReactNode | - | Custom image component for the step. |
icon | ReactNode | - | Icon component (used if no image provided). |
backgroundColor | string | - | Custom background color for the step. |
useOnboarding Hook
A hook for managing onboarding state in your application.
const {
hasCompletedOnboarding,
currentOnboardingStep,
setCurrentOnboardingStep,
completeOnboarding,
resetOnboarding,
skipOnboarding,
} = useOnboarding();
Returns
Property | Type | Description |
---|---|---|
hasCompletedOnboarding | boolean | Whether the user has completed onboarding. |
currentOnboardingStep | number | Current step index in the onboarding flow. |
setCurrentOnboardingStep | (step: number) => void | Function to set the current step. |
completeOnboarding | () => Promise<void> | Function to mark onboarding as completed. |
resetOnboarding | () => void | Function to reset onboarding state. |
skipOnboarding | () => Promise<void> | Function to skip and complete onboarding. |
Features
- Smooth Animations: Built with react-native-reanimated for fluid transitions
- Gesture Support: Swipe left/right to navigate between steps
- Customizable: Extensive customization options for styling and behavior
- Progress Indicators: Visual progress dots to show current step
- Flexible Content: Support for images, icons, and custom content
- State Management: Built-in hook for managing onboarding state
- Accessibility: Built with accessibility features in mind
- TypeScript: Full TypeScript support with proper type definitions
Accessibility
The Onboarding component is built with accessibility in mind:
- Proper semantic structure for screen readers
- Keyboard navigation support
- High contrast support for progress indicators
- Descriptive labels for navigation buttons
- Support for dynamic text sizing
- Focus management between steps