React Native

Multi-Step Progress Components in React Native

TTCOctober 28, 202510 Mins
Multi-Step Progress Components in React Native

Building Beautiful Multi-Step Progress Components in React Native: A Complete Guide

Creating reusable, customizable stepper components for onboarding flows, checkout processes, and multi-step user experiences


Introduction

In modern mobile applications, multi-step processes are everywhere - from user onboarding to checkout flows, from account setup to complex wizards. A well-designed progress indicator not only helps users understand where they are in a process but also provides visual feedback that keeps them engaged.

In this blog post, I'll walk you through building a comprehensive stepper progress component system for React Native that includes both horizontal and vertical orientations, with full customization capabilities and TypeScript support.

What We're Building

Our stepper component system includes:

  • Horizontal Stepper: Perfect for compact layouts and simple progress indication
  • Vertical Stepper: Ideal for detailed step information and longer processes
  • Full TypeScript Support: Type-safe props and interfaces
  • Customizable Styling: Colors, sizes, and visual states
  • Production Ready: Clean code, proper error handling, and responsive design

Project Setup

Let's start by setting up our React Native project with Expo:

# Create a new Expo project
npx create-expo-app stepper-progress --template blank-typescript
cd stepper-progress

# Install dependencies
npm install

Core Component Architecture

Step Interface

First, let's define our core data structure:

export interface Step {
    label: string;
    description?: string;
}

This simple interface allows us to define steps with required labels and optional descriptions, making our components flexible for different use cases.

Horizontal Stepper Component

The horizontal stepper is perfect for compact layouts and provides a clean, linear progress indication:

interface StepperProgressProps {
    steps: Step[];
    currentStep: number;
    activeColor?: string;
    inactiveColor?: string;
    completedColor?: string;
    labelStyle?: 'below' | 'inline' | 'none';
    showDescription?: boolean;
}

Key Features:

  • Circular step indicators with numbers or checkmarks
  • Connecting lines between steps
  • Color-coded states (active, completed, inactive)
  • Optional step labels and descriptions
  • Responsive design that adapts to different screen sizes

Visual States:

  • Inactive: Gray circles with step numbers
  • Active: Colored circle with enhanced shadow
  • Completed: Colored circle with checkmark

Vertical Stepper Component

The vertical stepper is ideal for detailed processes where you need more space for step information:

interface VerticalStepperProps {
    steps: Step[];
    currentStep: number;
    activeColor?: string;
    inactiveColor?: string;
    completedColor?: string;
    showDescription?: boolean;
}

Key Features:

  • Left-aligned circular indicators
  • Vertical connecting lines
  • Right-aligned step content
  • More space for descriptions
  • Better for longer step lists

Implementation Deep Dive

Step Circle Rendering

The core of our stepper is the step circle rendering logic:

const renderStepCircle = (index: number) => {
    const isCompleted = index < currentStep;
    const isActive = index === currentStep;
    const isFuture = index > currentStep;

    let circleColor = inactiveColor;
    if (isCompleted) circleColor = completedColor;
    if (isActive) circleColor = activeColor;

    return (
        <View style={styles.stepContainer} key={index}>
            <View style={styles.stepCircleContainer}>
                <View
                    style={[
                        styles.stepCircle,
                        { backgroundColor: circleColor },
                        isActive && styles.activeCircle,
                    ]}
                >
                    {isCompleted ? (
                        <Text style={styles.checkmark}>✓</Text>
                    ) : (
                        <Text
                            style={[
                                styles.stepNumber,
                                (isActive || isCompleted) && styles.stepNumberActive,
                            ]}
                        >
                            {index + 1}
                        </Text>
                    )}
                </View>
            </View>
            {/* Label rendering logic */}
        </View>
    );
};

Connector Rendering

The connectors between steps provide visual continuity:

const renderConnector = (index: number) => {
    if (index === steps.length - 1) return null;

    const isCompleted = index < currentStep;
    const connectorColor = isCompleted ? completedColor : inactiveColor;

    return (
        <View
            key={`connector-${index}`}
            style={[
                styles.connector,
                { backgroundColor: connectorColor },
            ]}
        />
    );
};

Styling Strategy

Our styling approach focuses on:

  1. Consistent Spacing: Using consistent margins and padding
  2. Visual Hierarchy: Different font weights and sizes for different elements
  3. State Indication: Clear visual differences between states
  4. Responsive Design: Flexible layouts that work on different screen sizes
const styles = StyleSheet.create({
    stepCircle: {
        width: 40,
        height: 40,
        borderRadius: 20,
        alignItems: 'center',
        justifyContent: 'center',
        elevation: 2,
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.1,
        shadowRadius: 4,
    },
    activeCircle: {
        elevation: 4,
        shadowOpacity: 0.2,
        shadowRadius: 6,
    },
    // ... more styles
});

Usage Examples

Basic Horizontal Stepper

import StepperProgress from './components/StepperProgress';

const steps = [
    { label: 'Welcome', description: 'Get started with your journey' },
    { label: 'Profile', description: 'Set up your personal information' },
    { label: 'Preferences', description: 'Customize your experience' },
    { label: 'Complete', description: 'You\'re all set!' },
];

<StepperProgress
    steps={steps}
    currentStep={currentStep}
    activeColor="#4F46E5"
    completedColor="#10B981"
    showDescription={true}
/>

Vertical Stepper with Custom Colors

import VerticalStepper from './components/VerticalStepper';

const checkoutSteps = [
    { label: 'Cart', description: 'Review your items' },
    { label: 'Shipping', description: 'Enter delivery address' },
    { label: 'Payment', description: 'Choose payment method' },
    { label: 'Confirm', description: 'Place your order' },
];

<VerticalStepper
    steps={checkoutSteps}
    currentStep={checkoutStep}
    activeColor="#7C3AED"
    completedColor="#059669"
    showDescription={true}
/>

Real-World Applications

1. User Onboarding

Perfect for guiding new users through app setup:

const onboardingSteps = [
    { label: 'Welcome', description: 'Get started with your journey' },
    { label: 'Profile', description: 'Set up your personal information' },
    { label: 'Preferences', description: 'Customize your experience' },
    { label: 'Complete', description: 'You\'re all set!' },
];

2. E-commerce Checkout

Streamline the purchase process:

const checkoutSteps = [
    { label: 'Cart', description: 'Review your items' },
    { label: 'Shipping', description: 'Enter delivery address' },
    { label: 'Payment', description: 'Choose payment method' },
    { label: 'Confirm', description: 'Place your order' },
];

3. Account Setup

Guide users through account creation:

const accountSteps = [
    { label: 'Email', description: 'Verify your email address' },
    { label: 'Password', description: 'Create a secure password' },
    { label: 'Profile', description: 'Add your personal details' },
    { label: 'Verification', description: 'Complete identity verification' },
];

Advanced Features

Custom Styling

Both components accept custom colors and can be easily styled:

<StepperProgress
    steps={steps}
    currentStep={currentStep}
    activeColor="#FF6B6B"      // Custom active color
    completedColor="#4ECDC4"   // Custom completed color
    inactiveColor="#E0E0E0"    // Custom inactive color
    showDescription={true}
/>

State Management Integration

The components work seamlessly with any state management solution:

const [currentStep, setCurrentStep] = useState(0);

const handleNext = () => {
    if (currentStep < steps.length - 1) {
        setCurrentStep(currentStep + 1);
    }
};

const handlePrevious = () => {
    if (currentStep > 0) {
        setCurrentStep(currentStep - 1);
    }
};

Best Practices

1. Step Definition

  • Keep step labels concise but descriptive
  • Use descriptions to provide additional context
  • Ensure steps are logically ordered

2. Visual Design

  • Use consistent colors throughout your app
  • Ensure good contrast for accessibility
  • Test on different screen sizes

3. User Experience

  • Provide clear navigation controls
  • Show progress percentage when helpful
  • Allow users to go back to previous steps when appropriate

4. Performance

  • Use React.memo for step components if needed
  • Avoid unnecessary re-renders
  • Optimize images and icons

Testing Your Components

Unit Testing

Test individual component behavior:

import { render } from '@testing-library/react-native';
import StepperProgress from './StepperProgress';

test('renders correct number of steps', () => {
    const steps = [
        { label: 'Step 1' },
        { label: 'Step 2' },
        { label: 'Step 3' },
    ];
  
    const { getByText } = render(
        <StepperProgress steps={steps} currentStep={0} />
    );
  
    expect(getByText('Step 1')).toBeTruthy();
    expect(getByText('Step 2')).toBeTruthy();
    expect(getByText('Step 3')).toBeTruthy();
});

Integration Testing

Test complete user flows:

test('navigates through all steps', async () => {
    const { getByText } = render(<App />);
  
    // Start at step 1
    expect(getByText('Step 1 of 4')).toBeTruthy();
  
    // Navigate to step 2
    fireEvent.press(getByText('Next'));
    expect(getByText('Step 2 of 4')).toBeTruthy();
  
    // Continue through all steps
    // ... additional test steps
});

Accessibility Considerations

Screen Reader Support

  • Use proper semantic markup
  • Provide meaningful labels
  • Announce step changes

Visual Accessibility

  • Ensure sufficient color contrast
  • Use icons alongside colors
  • Provide alternative text

Keyboard Navigation

  • Support keyboard navigation
  • Provide focus indicators
  • Handle keyboard shortcuts

Performance Optimization

Memoization

Use React.memo for expensive components:

const StepCircle = React.memo(({ step, index, isActive, isCompleted }) => {
    // Component implementation
});

Lazy Loading

Load step content only when needed:

const StepContent = React.lazy(() => import('./StepContent'));

// Use with Suspense
<Suspense fallback={<LoadingSpinner />}>
    <StepContent step={currentStep} />
</Suspense>

Deployment and Distribution

NPM Package

Create a reusable package:

{
    "name": "react-native-stepper-progress",
    "version": "1.0.0",
    "main": "dist/index.js",
    "types": "dist/index.d.ts",
    "files": ["dist"],
    "peerDependencies": {
        "react": ">=16.8.0",
        "react-native": ">=0.60.0"
    }
}

Documentation

  • Include comprehensive README
  • Provide live examples
  • Document all props and methods
  • Include TypeScript definitions

Conclusion

Building a comprehensive stepper progress component system for React Native involves careful consideration of design, usability, and technical implementation. The components we've built provide:

  • Flexibility: Both horizontal and vertical orientations
  • Customization: Extensive styling options
  • Type Safety: Full TypeScript support
  • Accessibility: Screen reader and keyboard support
  • Performance: Optimized rendering and state management

These components can be used in a wide variety of applications, from simple onboarding flows to complex multi-step processes. The key is to understand your users' needs and design the stepper experience accordingly.

Next Steps

  1. Extend the Components: Add animations, more styling options, or additional features
  2. Create Variations: Build specialized steppers for specific use cases
  3. Add Testing: Implement comprehensive test suites
  4. Optimize Performance: Profile and optimize for better performance
  5. Share with Community: Publish as an open-source package

Resources


This blog post demonstrates how to build production-ready stepper progress components for React Native. The complete source code is available in the accompanying repository, and you're free to use, modify, and distribute it according to your needs.

Happy coding! 🚀

Need help building your mobile app?

Let's talk about how we can help you design, build, and scale a high-performance React Native app tailored to your users.

Talk to an Expert