Skip to main content

Timeline Components

The Timeline Components provide chronological visualization and progress tracking functionality for the WorkPayCore Frontend application. These components handle step-by-step processes, progress indicators, and time-based event displays with consistent styling and behavior patterns.

Overview

This document covers timeline, stepper, and progress components that display chronological data, multi-step processes, and workflow progression throughout the application.

Components Overview

Core Timeline Components

Stepper Components

Progress Components


WPDotTimeline

A basic timeline component with dot indicators for displaying chronological events or process steps.

Component Location

import WPDotTimeline from 'components/Timeline/WpDotTimeline';

Props

PropTypeRequiredDefaultDescription
optionsTimelineOption[]-Array of timeline options

TypeScript Interface

interface TimelineOption {
title: string | ReactNode;
display: string | ReactNode;
icon?: ReactNode;
}

interface WPDotTimelineProps {
options: TimelineOption[];
}

Usage Examples

Basic Project Timeline

import WPDotTimeline from 'components/Timeline/WpDotTimeline';

function ProjectTimeline() {
const timelineOptions = [
{
title: 'Project Started',
display: 'Project initialization and team assignment completed.',
},
{
title: 'Development Phase',
display: 'Core features development in progress.',
},
{
title: 'Testing Phase',
display: 'Quality assurance and user acceptance testing.',
},
{
title: 'Deployment',
display: 'Production deployment and go-live.',
},
];

return <WPDotTimeline options={timelineOptions} />;
}

Timeline with Custom Icons

import WPDotTimeline from 'components/Timeline/WpDotTimeline';
import { CheckIcon, TimeIcon, WarningIcon } from '@chakra-ui/icons';

function ProcessTimeline() {
const processSteps = [
{
title: 'Application Submitted',
display: 'Application received and under review.',
icon: <CheckIcon color='green' />,
},
{
title: 'In Review',
display: 'Currently being reviewed by the team.',
icon: <TimeIcon color='orange' />,
},
{
title: 'Requires Attention',
display: 'Additional information needed.',
icon: <WarningIcon color='red' />,
},
];

return <WPDotTimeline options={processSteps} />;
}

Request History Timeline

function RequestHistoryTimeline({ request }) {
const historyOptions = request.history.map(event => ({
title: event.action,
display: `${event.user} - ${format(
new Date(event.date),
'MMM dd, yyyy HH:mm',
)}`,
}));

return <WPDotTimeline options={historyOptions} />;
}

WPCheckedTimeline

A timeline component with checkmark indicators, ideal for displaying completed steps or achievements.

Component Location

import WPCheckedTimeline from 'components/Timeline/WpCheckedTimeline';

Props

PropTypeRequiredDefaultDescription
optionsTimelineOption[]-Array of timeline options
spacingnumber--Spacing between items

TypeScript Interface

interface TimelineOption {
title?: ReactNode;
display?: ReactNode;
Icon?: ReactNode;
}

interface WPCheckedTimelineProps extends StackProps {
options: TimelineOption[];
}

Usage Examples

Onboarding Progress

import WPCheckedTimeline from 'components/Timeline/WpCheckedTimeline';

function OnboardingProgress() {
const onboardingSteps = [
{
title: 'Account Created',
display: 'User account has been successfully created.',
},
{
title: 'Profile Completed',
display: 'All required profile information has been provided.',
},
{
title: 'Training Completed',
display: 'Mandatory training sessions have been finished.',
},
];

return <WPCheckedTimeline options={onboardingSteps} />;
}

Approval Process

import WPCheckedTimeline from 'components/Timeline/WpCheckedTimeline';

function ApprovalTimeline({ approvals }) {
const approvalSteps = approvals.map(approval => ({
title: approval.stageName,
display: `Approved by ${approval.approverName} on ${format(
new Date(approval.date),
'MMM dd, yyyy',
)}`,
}));

return <WPCheckedTimeline options={approvalSteps} spacing={4} />;
}

Achievement Timeline

import WPCheckedTimeline from 'components/Timeline/WpCheckedTimeline';
import { TrophyIcon } from 'components/WPIcons';

function AchievementTimeline({ achievements }) {
const achievementSteps = achievements.map(achievement => ({
title: achievement.name,
display: achievement.description,
Icon: <TrophyIcon color='gold' />,
}));

return <WPCheckedTimeline options={achievementSteps} />;
}

WPTimelineConnector

The base timeline connector component that provides the visual connection line between timeline items.

Component Location

import WPTimelineConnector from 'components/Timeline/WPTimelineConnector';

Props

PropTypeRequiredDefaultDescription
childrenReactNode-Timeline items

TypeScript Interface

interface WPTimelineConnectorProps extends StackProps {
children: React.ReactNode;
}

Usage Examples

Custom Timeline Implementation

import WPTimelineConnector from 'components/Timeline/WPTimelineConnector';
import { VStack, Box, Text } from '@chakra-ui/react';

function CustomTimeline({ events }) {
return (
&lt;WPTimelineConnector&gt;
{events.map((event, idx) => (
<VStack key={idx} alignItems='flex-start' pl={4} position='relative'>
<Box
sx={{
width: '12px',
height: '12px',
bgColor: event.completed ? 'green' : 'gray.300',
borderRadius: '50%',
position: 'absolute',
top: 0,
left: '-6px',
}}
/>
<Text fontWeight='bold'>{event.title}</Text>
<Text color='gray.600'>{event.description}</Text>
</VStack>
))}
</WPTimelineConnector>
);
}

OnboardingStepper

The main onboarding progress indicator showing the 5-step onboarding process.

Component Location

import OnboardingStepper from 'components/OnboardingStepper';

Features

  • 5-step onboarding process
  • Progress bar visualization
  • Step completion indicators
  • Responsive design
  • Hide/show functionality

Onboarding Steps

  1. Create Organization - Basic organization setup
  2. Adjust Settings - Configuration and preferences
  3. Add People - Employee management setup
  4. Run Payroll - Payroll system configuration
  5. Choose Plan - Subscription plan selection

Usage Examples

Basic Onboarding Layout

import OnboardingStepper from 'components/OnboardingStepper';

function OnboardingLayout() {
return (
&lt;Box&gt;
<OnboardingStepper />
<Box p={8}>
<OnboardingContent />
</Box>
</Box>
);
}

Conditional Onboarding Display

import OnboardingStepper from 'components/OnboardingStepper';

function DashboardLayout({ user }) {
const showOnboarding = !user.onboardingCompleted;

return (
&lt;Box&gt;
{showOnboarding && <OnboardingStepper />}
<DashboardContent />
</Box>
);
}

Styling

  • Background: green-dark
  • Progress bar: whiteAlpha color scheme
  • Step indicators: Circular design with numbering
  • Responsive step layout

ProjectStepper

A simple stepper component for project creation workflows.

Component Location

import Stepper from 'containers/Timesheets/Projects/Stepper';

Props

PropTypeRequiredDefaultDescription
currentStepnumber-Current step index

Steps

  1. Project details - Basic project information
  2. Billing details - Billing and payment configuration

Usage Examples

Project Creation Flow

import Stepper from 'containers/Timesheets/Projects/Stepper';

function ProjectCreationWizard() {
const [currentStep, setCurrentStep] = useState(1);

return (
<VStack spacing={6}>
<Stepper currentStep={currentStep} />

{currentStep === 1 && (
<ProjectDetailsForm onNext={() => setCurrentStep(2)} />
)}

{currentStep === 2 && (
<BillingDetailsForm onBack={() => setCurrentStep(1)} />
)}
</VStack>
);
}

BulkUploadStepper

A stepper component specifically designed for bulk upload processes.

Component Location

import BulkUploadStepper from 'components/BulkUpload/BulkUploadStepper';

Props

PropTypeRequiredDefaultDescription
stepsstring[]-Array of step names
titlestring-Stepper title

Usage Examples

Employee Bulk Upload

import BulkUploadStepper from 'components/BulkUpload/BulkUploadStepper';

function EmployeeBulkUpload() {
const uploadSteps = [
'Download Template',
'Fill Data',
'Upload File',
'Review & Confirm',
'Process Complete',
];

return (
<BulkUploadStepper
steps={uploadSteps}
title='Employee Bulk Upload Progress'
/>
);
}

Payroll Data Upload

function PayrollBulkUpload() {
const payrollSteps = [
'Prepare Data',
'Validate Information',
'Upload Payroll',
'Review Results',
];

return <BulkUploadStepper steps={payrollSteps} title='Payroll Data Upload' />;
}

FormStepper

A comprehensive multi-step form stepper for various form workflows.

Component Location

import { FormStepper } from 'containers/People/Employee/AddEmployeeSingleEntry/Stepper';

Features

  • Multi-step form navigation
  • Form validation per step
  • Progress tracking
  • Back/Next navigation
  • Form state management

Usage Examples

Employee Registration Form

import { FormStepper } from 'containers/People/Employee/AddEmployeeSingleEntry/Stepper';

function EmployeeRegistrationModal() {
const [isOpen, setIsOpen] = useState(false);

return (
<FormStepper
isOpen={isOpen}
onClose={() => setIsOpen(false)}
option='add_employee'
onSuccess={() => {
setIsOpen(false);
// Refresh employee list
}}
/>
);
}

Company Setup Form

import { FormStepper } from 'containers/Settings/General/OrganisationSettings/CompaniesBranches/page/forms/AddCompany/Stepper';

function CompanySetupForm() {
return (
<FormStepper
onClose={() => navigate('/settings/companies')}
onSuccess={() => {
// Handle success
toast.success('Company created successfully');
}}
/>
);
}

WalletOptInStepper

A stepper component for wallet opt-in processes.

Component Location

import StepperWrapper from 'containers/MyWallet/Pages/OptIn/Forms/Stepper';

Steps

  1. Personal Details - User information collection
  2. Security Questions - Security setup
  3. PIN - PIN configuration

Usage Examples

Wallet Registration Flow

import StepperWrapper from 'containers/MyWallet/Pages/OptIn/Forms/Stepper';

function WalletRegistration() {
const [currentStep, setCurrentStep] = useState(1);

return (
<StepperWrapper
step={currentStep}
heading='Set up your wallet'
description='Complete the following steps to activate your wallet'
>
{currentStep === 1 && (
<PersonalDetailsForm onNext={() => setCurrentStep(2)} />
)}

{currentStep === 2 && (
<SecurityQuestionsForm
onNext={() => setCurrentStep(3)}
onBack={() => setCurrentStep(1)}
/>
)}

{currentStep === 3 && <PinSetupForm onBack={() => setCurrentStep(2)} />}
</StepperWrapper>
);
}

DayTimeline

A timeline component for visualizing daily time tracking and work intervals.

Component Location

import DayTimeline from 'containers/Timesheets/Employee/Timesheets/DayTimeline';

Props

PropTypeRequiredDefaultDescription
intervalsTimeInterval[]-Array of time intervals
totalTimeWorkedstring-Total time worked

TypeScript Interface

interface TimeInterval {
startTime: string;
endTime: string;
duration: number;
}

interface DayTimelineProps {
intervals: TimeInterval[];
totalTimeWorked: string;
}

Usage Examples

Employee Time Tracking

import DayTimeline from 'containers/Timesheets/Employee/Timesheets/DayTimeline';

function EmployeeTimesheetDay({ timesheetData }) {
const intervals = timesheetData.intervals.map(interval => ({
startTime: interval.clock_in,
endTime: interval.clock_out,
duration: interval.duration,
}));

return (
<DayTimeline
intervals={intervals}
totalTimeWorked={timesheetData.totalTime}
/>
);
}

WeekTimeline

A timeline component for visualizing weekly time tracking across multiple days.

Component Location

import WeekTimeline from 'containers/Timesheets/Employee/Timesheets/WeekTimeline';

Props

PropTypeRequiredDefaultDescription
dataWeekTimeData[]-Array of week time data
totalTimeWorkedstring-'00:00:00'Total time worked
isLoadingboolean-falseLoading state

Usage Examples

Weekly Timesheet View

import WeekTimeline from 'containers/Timesheets/Employee/Timesheets/WeekTimeline';

function WeeklyTimesheetView({ weekData, isLoading }) {
return (
<WeekTimeline
data={weekData}
totalTimeWorked={weekData.totalTime}
isLoading={isLoading}
/>
);
}

TimelineView

A comprehensive timeline component for displaying employee history and events.

Component Location

import TimelineView from 'containers/People/EmployeeHistory/components/TimelineView';

Features

  • Infinite scroll loading
  • Responsive design
  • Event categorization
  • Loading states
  • Mobile-friendly

Usage Examples

Employee History Timeline

import TimelineView from 'containers/People/EmployeeHistory/components/TimelineView';

function EmployeeHistoryPage() {
const [viewMode, setViewMode] = useState('timeline');

return (
<Stack spacing={6}>
<HStack justify='space-between'>
<ViewToggleButtons viewMode={viewMode} setViewMode={setViewMode} />
</HStack>

{viewMode === 'timeline' ? (
<TimelineView
timelineData={historyData}
isLoading={isLoading}
paginatedData={paginatedData}
field='all'
/>
) : (
<TableHistoryView {...tableProps} />
)}
</Stack>
);
}

ContractStatusProgress

A specialized progress component for EOR contract status tracking.

Component Location

import ViewContractStatusProgress from 'containers/EOR/Employees/components/ViewContractStatusProgress';

Features

  • Multi-stage contract process
  • Status indicators
  • Progress visualization
  • Step completion tracking

Contract Stages

  1. Employee details - Basic information entry
  2. Generate & Send Contract to Legal - Contract creation
  3. Legal Contract Review & Signoff - Legal validation
  4. Send Contract to Employee - Employee notification
  5. Employee Contract is Signed - Employee signature
  6. Employee Activated - Account activation

Usage Examples

EOR Contract Progress

function EORContractProgress({ contractData }) {
return (
<ViewContractStatusProgress
contractStatus={contractData.status}
currentStage={contractData.currentStage}
completedStages={contractData.completedStages}
/>
);
}

Stepper Patterns

Multi-Step Form Pattern

function MultiStepFormPattern() {
const [currentStep, setCurrentStep] = useState(0);
const [formData, setFormData] = useState({});

const steps = [
{ id: 1, label: 'Personal Info', component: PersonalInfoStep },
{ id: 2, label: 'Employment', component: EmploymentStep },
{ id: 3, label: 'Payment', component: PaymentStep },
{ id: 4, label: 'Review', component: ReviewStep },
];

const handleNext = () => {
setCurrentStep(prev => Math.min(steps.length - 1, prev + 1));
};

const handleBack = () => {
setCurrentStep(prev => Math.max(0, prev - 1));
};

const isLastStep = currentStep === steps.length - 1;
const isFirstStep = currentStep === 0;

return (
<VStack spacing={6}>
{/* Stepper Header */}
<HStack spacing={4} align='center' justify='space-between' w='100%'>
{steps.map((step, index) => {
const isActive = currentStep === index;
const isCompleted = currentStep > index;

return (
<Box
key={step.id}
borderRadius='32px'
px={2}
py={1}
border='1px solid #62A446'
bgColor={isActive || isCompleted ? 'green' : 'white'}
>
<HStack spacing={3}>
<Circle
size='28px'
bgColor={isActive || isCompleted ? 'white' : 'green'}
color={isActive || isCompleted ? 'green' : 'white'}
>
{isCompleted ? <CheckIcon /> : step.id}
</Circle>
<Text
fontSize='sm'
fontWeight='normal'
color={isActive || isCompleted ? 'white' : 'green'}
>
{step.label}
</Text>
</HStack>
</Box>
);
})}
</HStack>

{/* Step Content */}
<Box w='100%' minH='400px'>
{React.createElement(steps[currentStep].component, {
formData,
setFormData,
onNext: handleNext,
onBack: handleBack,
})}
</Box>

{/* Navigation */}
<HStack spacing={4} justify='space-between' w='100%'>
<Button variant='outline' onClick={handleBack} isDisabled={isFirstStep}>
Back
</Button>

<Button
colorScheme='green'
onClick={isLastStep ? handleSubmit : handleNext}
>
{isLastStep ? 'Submit' : 'Next'}
</Button>
</HStack>
</VStack>
);
}

Progress Tracking Pattern

function ProgressTrackingPattern({ stages, currentStage }) {
const calculateProgress = () => {
const completedStages = stages.filter(stage => stage.completed).length;
return (completedStages / stages.length) * 100;
};

return (
<VStack spacing={4} w='100%'>
{/* Progress Bar */}
<Box w='100%'>
<Progress value={calculateProgress()} colorScheme='green' />
<Text textAlign='center' fontSize='sm' color='gray.600' mt={2}>
{stages.filter(stage => stage.completed).length} of {stages.length}{' '}
completed
</Text>
</Box>

{/* Timeline */}
&lt;WPTimelineConnector&gt;
{stages.map((stage, index) => (
<VStack
key={index}
alignItems='flex-start'
pl={4}
position='relative'
>
<Box
sx={{
width: '20px',
height: '20px',
borderRadius: '50%',
position: 'absolute',
top: 0,
left: '-10px',
border: '2px solid',
borderColor: stage.completed ? 'green' : 'gray.300',
bgColor: stage.completed ? 'green' : 'white',
}}
>
{stage.completed && <CheckIcon color='white' w='12px' h='12px' />}
</Box>

<Text
fontWeight='bold'
color={stage.completed ? 'green' : 'gray.600'}
>
{stage.title}
</Text>

<Text fontSize='sm' color='gray.600'>
{stage.description}
</Text>

{stage.completed && (
<Text fontSize='xs' color='green'>
Completed on{' '}
{format(new Date(stage.completedAt), 'MMM dd, yyyy')}
</Text>
)}
</VStack>
))}
</WPTimelineConnector>
</VStack>
);
}

Best Practices

Timeline Design

  1. Consistent Visual Language

    • Use consistent colors and spacing
    • Maintain uniform icon sizes
    • Apply consistent typography
  2. Information Hierarchy

    • Place most important information first
    • Use clear visual distinctions between completed and pending items
    • Provide adequate white space
  3. Interactive Elements

    • Make clickable elements obvious
    • Provide hover states
    • Include keyboard navigation support

Progress Tracking

  1. Clear Progress Indicators

    • Show current position clearly
    • Indicate completed vs. pending steps
    • Provide progress percentage when helpful
  2. Error Handling

    • Handle validation errors gracefully
    • Allow users to fix errors and continue
    • Provide clear error messages
  3. State Management

    • Persist progress across page refreshes
    • Handle browser navigation properly
    • Maintain form state during multi-step processes

Performance

  1. Efficient Rendering

    • Use React.memo for timeline items
    • Implement virtualization for long timelines
    • Optimize re-renders with proper dependencies
  2. Data Loading

    • Implement progressive loading for large datasets
    • Use skeleton states during loading
    • Cache timeline data appropriately

Accessibility

  1. Screen Reader Support

    • Provide proper ARIA labels
    • Use semantic HTML structure
    • Announce progress changes
  2. Keyboard Navigation

    • Support tab navigation
    • Provide keyboard shortcuts for common actions
    • Handle focus management properly
  3. Visual Accessibility

    • Ensure sufficient color contrast
    • Don't rely solely on color to convey information
    • Support different font sizes

Testing

Unit Tests

import { render, screen } from '@testing-library/react';
import WPDotTimeline from 'components/Timeline/WpDotTimeline';

describe('WPDotTimeline', () => {
it('renders timeline options correctly', () => {
const options = [
{ title: 'Step 1', display: 'First step description' },
{ title: 'Step 2', display: 'Second step description' },
];

render(<WPDotTimeline options={options} />);

expect(screen.getByText('Step 1')).toBeInTheDocument();
expect(screen.getByText('First step description')).toBeInTheDocument();
expect(screen.getByText('Step 2')).toBeInTheDocument();
expect(screen.getByText('Second step description')).toBeInTheDocument();
});

it('renders custom icons when provided', () => {
const options = [
{
title: 'Step 1',
display: 'Description',
icon: <div data-testid='custom-icon'>Custom Icon</div>,
},
];

render(<WPDotTimeline options={options} />);

expect(screen.getByTestId('custom-icon')).toBeInTheDocument();
});
});

Integration Tests

describe('FormStepper', () => {
it('navigates through steps correctly', async () => {
const { user } = render(<FormStepper />);

// Start at step 1
expect(screen.getByText('Personal profile')).toBeInTheDocument();

// Click next
await user.click(screen.getByText('Next'));

// Should be at step 2
expect(screen.getByText('Employment profile')).toBeInTheDocument();

// Click back
await user.click(screen.getByText('Back'));

// Should be back at step 1
expect(screen.getByText('Personal profile')).toBeInTheDocument();
});

it('validates form data before proceeding', async () => {
const { user } = render(<FormStepper />);

// Try to proceed without filling required fields
await user.click(screen.getByText('Next'));

// Should show validation errors
expect(screen.getByText('This field is required')).toBeInTheDocument();
});
});

Migration Guide

From Legacy Timeline Components

  1. Update Import Paths

    // Old
    import Timeline from 'components/Timeline/OldTimeline';

    // New
    import WPDotTimeline from 'components/Timeline/WpDotTimeline';
  2. Update Data Structure

    // Old
    const timelineData = {
    events: [
    { name: 'Event 1', description: 'Description 1' },
    { name: 'Event 2', description: 'Description 2' },
    ],
    };

    // New
    const timelineOptions = [
    { title: 'Event 1', display: 'Description 1' },
    { title: 'Event 2', display: 'Description 2' },
    ];
  3. Update Component Usage

    // Old
    <Timeline data={timelineData} />

    // New
    <WPDotTimeline options={timelineOptions} />

From Basic Stepper to FormStepper

  1. Wrap in Form Provider

    // Old
    <BasicStepper steps={steps} />

    // New
    <FormProvider {...methods}>
    <FormStepper onSuccess={handleSuccess} />
    </FormProvider>
  2. Update Step Configuration

    // Old
    const steps = ['Step 1', 'Step 2', 'Step 3'];

    // New - Steps are now defined within the FormStepper component
    // Configuration is handled internally
  3. Handle Form Submission

    // Old
    const handleSubmit = data => {
    // Handle submission
    };

    // New
    const handleSuccess = success => {
    if (success) {
    // Handle successful submission
    }
    };

Styling Customization

Timeline Connector Styling

// Custom timeline connector with different styling
const CustomTimelineConnector = styled(WPTimelineConnector)`
border-left: 2px dashed #62a446;

&::before {
content: '';
position: absolute;
top: 0;
left: -1px;
width: 2px;
height: 20px;
background: linear-gradient(to bottom, transparent, #62a446);
}
`;

Stepper Color Customization

const customStepperTheme = {
completed: {
bg: '#62a446',
color: 'white',
border: '#62a446',
},
active: {
bg: '#62a446',
color: 'white',
border: '#62a446',
},
inactive: {
bg: 'white',
color: '#62a446',
border: '#62a446',
},
};

Timeline Item Customization

const TimelineItem = ({ item, isCompleted }) => (
<VStack alignItems='flex-start' pl={4} position='relative'>
<Box
sx={{
width: '16px',
height: '16px',
borderRadius: '50%',
position: 'absolute',
top: 0,
left: '-8px',
bg: isCompleted ? 'green.500' : 'gray.300',
border: '2px solid white',
boxShadow: '0 0 0 2px',
boxShadowColor: isCompleted ? 'green.500' : 'gray.300',
}}
/>
<Text fontWeight='semibold' color={isCompleted ? 'green.700' : 'gray.600'}>
{item.title}
</Text>
<Text fontSize='sm' color='gray.600'>
{item.description}
</Text>
</VStack>
);