Skip to main content

Top-Level Components

Top-level components are individual utility components that provide specific functionality without requiring their own directory structure. These components handle common patterns like text truncation, modals, toggles, navigation, and form inputs.

Overview

This document covers standalone components that are directly placed in the src/components/ directory and provide focused functionality for the WorkPayCore Frontend application.

Components Overview

Text & Display Components

  • WPTruncateText - Text truncation with tooltip
  • ComingSoon - Empty state for features under development
  • UnderMaintenance - System maintenance page
  • WPModal - Basic modal wrapper with customizable width

Input Components

Toggle Components

  • ToggleSwitchOne - Multi-option toggle switch
  • ToggleSwitch - Basic toggle switch

Utility Components

  • ScrollToTop - Scroll to top functionality
  • ProtectedRoutes - Route protection wrapper
  • RenewSubscription - Subscription renewal component

WPTruncateText

A component that truncates text with a tooltip if it exceeds the maximum length. Shows the full text in a tooltip on hover.

Component Location

import WPTruncatedText from 'components/WPTruncateText';

Props

PropTypeRequiredDefaultDescription
textToTruncatestring-The text to be truncated
maxLengthnumber-16Maximum length before truncation occurs

TypeScript Interface

interface WPTruncatedTextProps {
textToTruncate: string;
maxLength?: number;
}

Usage Examples

Basic Usage

import WPTruncatedText from 'components/WPTruncateText';

function UserName() {
return (
<WPTruncatedText
textToTruncate='This is a very long user name that needs truncation'
maxLength={20}
/>
);
}

Default Length

import WPTruncatedText from 'components/WPTruncateText';

function FileName() {
return (
<WPTruncatedText textToTruncate='very-long-filename-that-exceeds-default-length.pdf' />
);
}

Styling

  • Uses textStyle='body-small' from theme
  • Font weight: semi-bold
  • Font size: 13px
  • White space: nowrap
  • Tooltip placement: top-start

Accessibility

  • Tooltip shows full text when truncated
  • Supports keyboard navigation
  • Screen reader accessible through tooltip

ComingSoon

Empty state component for features under development or maintenance.

Component Location

import ComingSoon from 'components/ComingSoon';

Props

PropTypeRequiredDefaultDescription
pagestring--Page/feature name
pluralboolean-falseUse plural form
variantstring--Variant (maintenance, under-maintenance)

TypeScript Interface

interface ComingSoonProps {
page?: string;
plural?: boolean;
variant?: 'maintenance' | 'under-maintenance';
}

Usage Examples

Feature Coming Soon

import ComingSoon from 'components/ComingSoon';

function ReportsPage() {
return <ComingSoon page='Reports' plural={true} />;
}

Under Maintenance

import ComingSoon from 'components/ComingSoon';

function DashboardPage() {
return <ComingSoon page='Dashboard' variant='maintenance' />;
}

System Maintenance

import ComingSoon from 'components/ComingSoon';

function MaintenancePage() {
return <ComingSoon variant='under-maintenance' />;
}

Styling

  • Uses background image from assets/images/ComingSoon.svg
  • Centered layout with VStack
  • Logo positioned absolutely for maintenance variant
  • Responsive typography

WPModal

Basic modal wrapper component with customizable width and loading states.

Component Location

import WPModal from 'components/WPModal';

Props

PropTypeRequiredDefaultDescription
headingstring-Modal heading text
isOpenboolean-Modal open state
handleClosefunction-Close handler function
childrenReactNode-Modal content
customWidthstring-Custom modal width
isLoadingboolean-falseLoading state
isCenteredboolean-falseCenter modal

TypeScript Interface

interface WPModalProps {
heading: string;
isOpen: boolean;
handleClose: () => void;
children: React.ReactNode;
customWidth: string;
isLoading?: boolean;
isCentered?: boolean;
}

Usage Examples

Basic Modal

import WPModal from 'components/WPModal';

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

return (
<WPModal
heading='Edit User'
isOpen={isOpen}
handleClose={() => setIsOpen(false)}
customWidth='600px'
>
<UserForm />
</WPModal>
);
}

Loading Modal

import WPModal from 'components/WPModal';

function SaveModal() {
const [isLoading, setIsLoading] = useState(false);

return (
<WPModal
heading='Saving Changes'
isOpen={isOpen}
handleClose={() => setIsOpen(false)}
customWidth='400px'
isLoading={isLoading}
>
&lt;Text&gt;Please wait while we save your changes...</Text>
</WPModal>
);
}

Styling

  • Header font size: 28px
  • Header padding bottom: 0
  • Text transform: capitalize
  • Closes on overlay click (disabled when loading)
  • Close button disabled during loading

WPNumberInput

Numeric input component with validation and React Hook Form integration.

Component Location

import { WPNumberInput, WPNumberInput2 } from 'components/WPNumberInput';

Props

WPNumberInput Props

PropTypeRequiredDefaultDescription
namestring-Input name
controlControl-React Hook Form control
placeholderstring-Input placeholder
requiredboolean-falseRequired field
defaultValuenumber--Default value
rulesobject--Additional validation rules
stylesobject--Custom styles

WPNumberInput2 Props

PropTypeRequiredDefaultDescription
namestring-Input name
controlControl-React Hook Form control
labelstring-Input label
placeholderstring-Input placeholder
isRequiredboolean-falseRequired field
isDisabledboolean-falseDisabled state
errorFieldError--Error object
helperTextstring--Helper text
sizestring-'sm'Input size
inputModestring-'numeric'Input mode

TypeScript Interface

interface WPNumberInputProps {
name: string;
control: Control;
placeholder: string;
required?: boolean;
defaultValue?: number;
rules?: object;
styles?: object;
}

interface WPNumberInput2Props {
name: string;
control: Control;
label: string;
placeholder: string;
isRequired?: boolean;
isDisabled?: boolean;
error?: FieldError;
helperText?: string;
size?: string;
inputMode?: string;
}

Usage Examples

Basic Usage

import { WPNumberInput } from 'components/WPNumberInput';
import { useForm } from 'react-hook-form';

function AccruedDaysForm() {
const {
control,
formState: { errors },
} = useForm();

return (
<FormControl isInvalid={errors.days_accrued}>
<FormLabel isRequired>ACCRUED DAYS</FormLabel>
<WPNumberInput
name='days_accrued'
control={control}
placeholder='Enter number of days'
required
/>
&lt;FormErrorMessage&gt;{errors.days_accrued?.message}</FormErrorMessage>
</FormControl>
);
}

Advanced Usage (WPNumberInput2)

import { WPNumberInput2 } from 'components/WPNumberInput';
import { useForm } from 'react-hook-form';

function SalaryForm() {
const {
control,
formState: { errors },
} = useForm();

return (
<WPNumberInput2
name='salary'
control={control}
label='Monthly Salary'
placeholder='Enter salary amount'
isRequired
error={errors.salary}
helperText='Enter amount in local currency'
size='md'
/>
);
}

Validation

  • Built-in pattern validation: /^[1-9]\d*$/
  • Custom validation messages
  • Required field validation
  • Numeric keyboard on mobile devices

Styling

  • Focus border color: green
  • Form control integration
  • Error state styling
  • Helper text support

ToggleSwitchOne

Multi-option toggle switch component with customizable styling and loading states.

Component Location

import ToggleSwitchOne from 'components/ToggleSwitchOne';

Props

PropTypeRequiredDefaultDescription
optionsArray-Array of option objects
selectedobject-Currently selected option
handleChangefunction-Change handler
namestring-Form field name
isLoadingboolean-falseLoading state
isDisabledboolean-falseDisabled state
minWidthnumber-100Minimum width per option

TypeScript Interface

interface ToggleSwitchOneProps {
options: Array<{
value: string | number;
label: string;
}>;
selected: {
value: string | number;
label: string;
};
handleChange: (value: any) => void;
name: string;
isLoading?: boolean;
isDisabled?: boolean;
minWidth?: number;
}

Usage Examples

Basic Toggle

import ToggleSwitchOne from 'components/ToggleSwitchOne';

function StatusToggle() {
const [selected, setSelected] = useState({
value: 'active',
label: 'Active',
});

const options = [
{ value: 'active', label: 'Active' },
{ value: 'inactive', label: 'Inactive' },
{ value: 'pending', label: 'Pending' },
];

return (
<ToggleSwitchOne
options={options}
selected={selected}
handleChange={setSelected}
name='status'
/>
);
}

Loading State

import ToggleSwitchOne from 'components/ToggleSwitchOne';

function PayrollToggle() {
const [isLoading, setIsLoading] = useState(false);

const handleChange = async value => {
setIsLoading(true);
// API call
await updatePayrollStatus(value);
setIsLoading(false);
};

return (
<ToggleSwitchOne
options={payrollOptions}
selected={currentStatus}
handleChange={handleChange}
name='payroll_status'
isLoading={isLoading}
minWidth={120}
/>
);
}

Styling

  • Background color: skeletonTable
  • Border radius: 28px
  • Height: 35px
  • Animated selection indicator
  • Loading spinner integration
  • Cursor states for disabled/loading

Global application sidebar with navigation menu for multi-tenant applications.

Component Location

import GlobalSidebar from 'components/GlobalSidebar';

Features

  • Role-based navigation (admin/employee views)
  • Feature flag integration
  • Permission-based access control
  • Subscription-based menu visibility
  • Hierarchical menu structure
  • Remote payroll support
  • Country-specific features

Usage Examples

Basic Usage

import GlobalSidebar from 'components/GlobalSidebar';

function AppLayout() {
return (
&lt;Flex&gt;
<GlobalSidebar />
<Box flex={1}>
<MainContent />
</Box>
</Flex>
);
}

Employee Menu Items

  • Home
  • People (with submenus)
  • Payroll (with submenus)
  • Expenses
  • Leave
  • Performance Management
  • Documents

Admin Menu Items

  • All employee items plus:
  • Settings
  • Analytics
  • Billing
  • Admin tools

Integration

  • Works with feature flags system
  • Integrates with subscription status
  • Supports remote payroll switching
  • Country-specific menu items

OnboardingStepper

Onboarding progress indicator showing completion steps.

Component Location

import OnboardingStepper from 'components/OnboardingStepper';

Features

  • 5-step onboarding process
  • Progress visualization
  • Step completion indicators
  • Responsive design

Usage Examples

Basic Usage

import OnboardingStepper from 'components/OnboardingStepper';

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

Steps

  1. Create Organization
  2. Adjust Settings
  3. Add People
  4. Run Payroll
  5. Choose Plan

Styling

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

ScrollArea

Custom scrollable area with styled scrollbar and drag functionality.

Component Location

import ScrollArea from 'components/ScrollArea';

Props

PropTypeRequiredDefaultDescription
childrenReactNode-Scrollable content
scrollThumbColorstring-'whiteAlpha.500'Scroll thumb color

Features

  • Custom scrollbar styling
  • Drag-to-scroll functionality
  • Hidden native scrollbars
  • Smooth scrolling animation
  • Responsive thumb sizing

Usage Examples

Basic Usage

import ScrollArea from 'components/ScrollArea';

function LongContent() {
return (
&lt;ScrollArea&gt;
<Box height='2000px'>
&lt;Text&gt;Very long content that needs scrolling...</Text>
</Box>
</ScrollArea>
);
}

Custom Thumb Color

import ScrollArea from 'components/ScrollArea';

function CustomScrollArea() {
return (
<ScrollArea scrollThumbColor='green.500'>
<LongContentList />
</ScrollArea>
);
}

Styling

  • Hidden native scrollbars
  • Custom thumb appearance
  • Hover states
  • Drag states
  • Responsive sizing

BoxInput

Read-only input display component that mimics input styling.

Component Location

import BoxInput from 'components/BoxInput';

Props

PropTypeRequiredDefaultDescription
titlestring-'This is a readonly field'Tooltip text
widthstring-'full'Input width
isDisabledboolean-falseDisabled state
isRequiredboolean-falseRequired field
labelstring--Field label
labelSizestring-'md'Label size
childrenReactNode--Input content

TypeScript Interface

interface BoxInputProps {
title?: string;
width?: string;
isDisabled?: boolean;
isRequired?: boolean;
label?: string;
labelSize?: string;
children?: React.ReactNode;
}

Usage Examples

Basic Usage

import BoxInput from 'components/BoxInput';

function ReadOnlyField() {
return (
<BoxInput label='Employee ID' title='This field is automatically generated'>
&lt;Text&gt;EMP-001</Text>
</BoxInput>
);
}

Disabled State

import BoxInput from 'components/BoxInput';

function DisabledField() {
return (
<BoxInput
label='Calculated Value'
isDisabled
title='This value is calculated automatically'
>
&lt;Text&gt;$5,000.00</Text>
</BoxInput>
);
}

Styling

  • Background color: #F2F2F2
  • Border: 1px transparent
  • Height: 2.5rem
  • Padding: 1rem
  • Disabled opacity: 0.8
  • Cursor: not-allowed when disabled

UnderMaintenance

System maintenance page with contact information and support channels.

Component Location

import { UnderMaintenance } from 'components/UnderMaintenance';

Features

  • Full-page maintenance message
  • Contact information with copy functionality
  • Country-specific phone numbers
  • Support email integration
  • Responsive design

Usage Examples

Basic Usage

import { UnderMaintenance } from 'components/UnderMaintenance';

function MaintenancePage() {
return <UnderMaintenance />;
}

Contact Channels

  • Email: support@myworkpay.com
  • Kenya: +254 711 082123 / +254 730 731303
  • Nigeria: +234 810 401 5886 / +234 906 382 9334
  • Uganda: +256 323 200 740

Styling

  • Centered layout
  • Logo positioning
  • Country flag integration
  • Copy-to-clipboard functionality
  • Responsive design

Migration Notes

Breaking Changes

  • WPNumberInput: Updated validation patterns
  • GlobalSidebar: New menu structure for remote payroll
  • ToggleSwitchOne: Improved loading states

Deprecation Warnings

  • Old modal patterns should migrate to WPModal
  • Legacy number inputs should use WPNumberInput2

Upgrade Paths

  1. Replace old text truncation with WPTruncateText
  2. Update modal implementations to use WPModal
  3. Migrate number inputs to WPNumberInput2
  4. Update sidebar implementations to use GlobalSidebar

Best Practices

Text Truncation

  • Use appropriate maxLength based on container width
  • Provide meaningful tooltips
  • Consider responsive truncation lengths
  • Always provide proper close handlers
  • Use loading states for async operations
  • Set appropriate modal widths

Number Inputs

  • Use proper validation rules
  • Provide clear error messages
  • Set appropriate input modes for mobile
  • Implement proper permission checks
  • Use feature flags for conditional navigation
  • Provide clear visual hierarchy

Scrolling

  • Use ScrollArea for custom scroll styling
  • Implement proper keyboard navigation
  • Consider mobile scroll behavior

Accessibility

General Guidelines

  • All components support keyboard navigation
  • Proper ARIA attributes where applicable
  • Screen reader friendly implementations
  • High contrast mode support

Specific Features

  • WPTruncateText: Tooltip accessibility
  • WPModal: Focus management
  • ToggleSwitchOne: Keyboard selection
  • GlobalSidebar: Navigation accessibility
  • ScrollArea: Keyboard scrolling support

Performance Considerations

Optimization Tips

  • Use React.memo for expensive components
  • Implement proper loading states
  • Optimize menu rendering with visibility checks
  • Use efficient scroll handling

Memory Management

  • Proper cleanup in useEffect hooks
  • Event listener removal
  • Animation frame cancellation
  • Ref cleanup

Testing Strategies

Unit Testing

  • Test prop validation
  • Test state changes
  • Test event handlers
  • Test accessibility features

Integration Testing

  • Test with React Hook Form
  • Test navigation flows
  • Test permission systems
  • Test responsive behavior

E2E Testing

  • Test complete user flows
  • Test accessibility compliance
  • Test performance metrics
  • Test cross-browser compatibility