Skip to main content

Button Components

The Button Components provide specialized button functionality for the WorkPayCore Frontend application. These components extend Chakra UI's Button component with WorkPay-specific styling, icons, and behaviors for common actions like exporting, filtering, and downloading.

Overview

This document covers all specialized button components that provide consistent styling and functionality for specific actions throughout the application.

Components Overview

Action Buttons

Icon Buttons


WPExportAction

A specialized button for export actions with consistent styling and upload icon.

Component Location

import WPExportAction from 'components/Button/WPExportAction';

Props

PropTypeRequiredDefaultDescription
handleClickfunction-Click handler for export action
sizestring-'sm'Button size
...propsButtonProps--Additional Chakra UI Button props

TypeScript Interface

interface WPExportActionProps extends ButtonProps {
handleClick: () => void;
size?: string;
}

Features

Consistent Styling

  • Outline variant with border-1 color
  • Grey text color (hue-grey.700)
  • Upload icon on the right side
  • Small size by default

Export Integration

  • Designed for data export functionality
  • Consistent visual pattern across the application
  • Proper accessibility with aria-label

Usage Examples

Basic Export Button

import WPExportAction from 'components/Button/WPExportAction';

function DataTable() {
const handleExport = () => {
// Export logic
exportTableData();
};

return (
<VStack>
<HStack justify='space-between'>
&lt;Heading&gt;Employee Data</Heading>
<WPExportAction handleClick={handleExport} />
</HStack>
&lt;Table&gt;{/* Table content */}</Table>
</VStack>
);
}

Custom Size Export Button

import WPExportAction from 'components/Button/WPExportAction';

function ReportsPage() {
const handleExportReport = () => {
generateReport();
};

return (
&lt;Card&gt;
&lt;CardHeader&gt;
<HStack justify='space-between'>
<Heading size='md'>Monthly Report</Heading>
<WPExportAction handleClick={handleExportReport} size='md' />
</HStack>
</CardHeader>
&lt;CardBody&gt;
<ReportContent />
</CardBody>
</Card>
);
}

Disabled Export Button

import WPExportAction from 'components/Button/WPExportAction';

function ConditionalExport({ hasData }) {
const handleExport = () => {
if (hasData) {
exportData();
}
};

return (
<WPExportAction
handleClick={handleExport}
isDisabled={!hasData}
opacity={hasData ? 1 : 0.4}
/>
);
}

Styling

  • Variant: Outline
  • Border Color: border-1
  • Text Color: hue-grey.700
  • Icon: UploadSolid (right side)
  • Default Size: Small (sm)

WPFilterAction

A specialized button for filter actions with consistent styling and filter icon.

Component Location

import WPFilterAction from 'components/Button/WPFilterAction';

Props

PropTypeRequiredDefaultDescription
handleClickfunction-Click handler for filter action
sizestring-'sm'Button size
...propsButtonProps--Additional Chakra UI Button props

TypeScript Interface

interface WPFilterActionProps extends ButtonProps {
handleClick: () => void;
size?: string;
}

Features

Consistent Styling

  • Outline variant with border-1 color
  • Grey text color (hue-grey.700)
  • Filter icon on the right side
  • Small size by default

Filter Integration

  • Designed for filter functionality
  • Consistent visual pattern across the application
  • Proper accessibility with aria-label

Usage Examples

Basic Filter Button

import WPFilterAction from 'components/Button/WPFilterAction';

function EmployeeList() {
const [isFilterOpen, setIsFilterOpen] = useState(false);

const handleFilter = () => {
setIsFilterOpen(true);
};

return (
&lt;VStack&gt;
<HStack justify='space-between'>
&lt;Heading&gt;Employees</Heading>
<WPFilterAction handleClick={handleFilter} />
</HStack>
<EmployeeTable />
<FilterDrawer
isOpen={isFilterOpen}
onClose={() => setIsFilterOpen(false)}
/>
</VStack>
);
}

Filter with Badge

import WPFilterAction from 'components/Button/WPFilterAction';

function FilterWithCount({ activeFilters }) {
const handleFilterClick = () => {
openFilterModal();
};

return (
&lt;HStack&gt;
<WPFilterAction handleClick={handleFilterClick} />
{activeFilters > 0 && (
<Badge colorScheme='blue' borderRadius='full'>
{activeFilters}
</Badge>
)}
</HStack>
);
}

Filter Button States

import WPFilterAction from 'components/Button/WPFilterAction';

function StatefulFilter() {
const [isFiltering, setIsFiltering] = useState(false);

const handleFilter = async () => {
setIsFiltering(true);
try {
await applyFilters();
} finally {
setIsFiltering(false);
}
};

return (
<WPFilterAction
handleClick={handleFilter}
isLoading={isFiltering}
loadingText='Filtering...'
/>
);
}

Styling

  • Variant: Outline
  • Border Color: border-1
  • Text Color: hue-grey.700
  • Icon: FilterOutline (right side)
  • Default Size: Small (sm)

CustomIconButton

A highly customizable icon button with tooltip support and consistent styling.

Component Location

import CustomIconButton from 'components/Button/CustomIconButton';

Props

PropTypeRequiredDefaultDescription
iconReactNode-Icon element to display
labelstring-Aria-label and tooltip text
sizestring-'sm'Button size
noTooltipboolean-falseDisable tooltip display
...restobject--Additional IconButton props

TypeScript Interface

interface CustomIconButtonProps {
icon: React.ReactNode;
label: string;
size?: string;
noTooltip?: boolean;
[key: string]: any;
}

Features

Tooltip Integration

  • Automatic tooltip with label text
  • Option to disable tooltip with noTooltip prop
  • Proper accessibility with aria-label

Size Variants

  • Multiple size options (sm, md, lg)
  • Consistent sizing across the application
  • Responsive icon sizing

Disabled State Handling

  • Proper disabled cursor styles
  • Opacity changes for disabled state
  • Hover and focus state management

Usage Examples

Basic Icon Button

import CustomIconButton from 'components/Button/CustomIconButton';
import { EditSolid } from 'components/WPIcons';

function EditButton() {
const handleEdit = () => {
// Edit logic
};

return (
<CustomIconButton
icon={<EditSolid />}
label='Edit employee'
onClick={handleEdit}
/>
);
}

Icon Button Without Tooltip

import CustomIconButton from 'components/Button/CustomIconButton';
import { DeleteSolid } from 'components/WPIcons';

function DeleteButton() {
return (
<CustomIconButton
icon={<DeleteSolid />}
label='Delete item'
onClick={handleDelete}
noTooltip
colorScheme='red'
/>
);
}

Different Sizes

import CustomIconButton from 'components/Button/CustomIconButton';
import { SettingsSolid } from 'components/WPIcons';

function SettingsButtons() {
return (
<HStack spacing={2}>
<CustomIconButton icon={<SettingsSolid />} label='Settings' size='sm' />
<CustomIconButton icon={<SettingsSolid />} label='Settings' size='md' />
<CustomIconButton icon={<SettingsSolid />} label='Settings' size='lg' />
</HStack>
);
}

Action Button Group

import CustomIconButton from 'components/Button/CustomIconButton';
import { EditSolid, DeleteSolid, ViewSolid } from 'components/WPIcons';

function ActionButtons({ onEdit, onDelete, onView }) {
return (
<HStack spacing={1}>
<CustomIconButton
icon={<ViewSolid />}
label='View details'
onClick={onView}
variant='ghost'
/>
<CustomIconButton
icon={<EditSolid />}
label='Edit item'
onClick={onEdit}
variant='outline'
/>
<CustomIconButton
icon={<DeleteSolid />}
label='Delete item'
onClick={onDelete}
variant='outline'
colorScheme='red'
/>
</HStack>
);
}

Styling

  • Variants: Supports all Chakra UI IconButton variants
  • Sizes: sm, md, lg with consistent scaling
  • Disabled State: Opacity 0.4, not-allowed cursor
  • Tooltip: Arrow tooltip with label text

DownloadButton

A specialized icon button for download actions with consistent styling and download icon.

Component Location

import DownloadButton from 'components/Button/DownloadButton';

Props

PropTypeRequiredDefaultDescription
labelstring-Aria-label and tooltip text
sizestring-'sm'Button size
...restobject--Additional IconButton props

TypeScript Interface

interface DownloadButtonProps {
label: string;
size?: string;
[key: string]: any;
}

Features

Download Icon

  • Pre-configured with DownloadSolid icon
  • White fill color for visibility
  • Consistent 20px sizing

Tooltip Integration

  • Automatic tooltip with label text
  • Proper accessibility with aria-label

Usage Examples

Basic Download Button

import DownloadButton from 'components/Button/DownloadButton';

function FileDownload() {
const handleDownload = () => {
downloadFile();
};

return <DownloadButton label='Download report' onClick={handleDownload} />;
}

Download with Loading State

import DownloadButton from 'components/Button/DownloadButton';

function AsyncDownload() {
const [isDownloading, setIsDownloading] = useState(false);

const handleDownload = async () => {
setIsDownloading(true);
try {
await downloadFile();
} finally {
setIsDownloading(false);
}
};

return (
<DownloadButton
label='Download file'
onClick={handleDownload}
isLoading={isDownloading}
/>
);
}

Download Button in Table

import DownloadButton from 'components/Button/DownloadButton';

function FileTable({ files }) {
const handleDownload = file => {
downloadFileById(file.id);
};

return (
&lt;Table&gt;
&lt;Thead&gt;
&lt;Tr&gt;
&lt;Th&gt;Name</Th>
&lt;Th&gt;Size</Th>
&lt;Th&gt;Actions</Th>
</Tr>
</Thead>
&lt;Tbody&gt;
{files.map(file => (
<Tr key={file.id}>
&lt;Td&gt;{file.name}</Td>
&lt;Td&gt;{file.size}</Td>
&lt;Td&gt;
<DownloadButton
label={`Download ${file.name}`}
onClick={() => handleDownload(file)}
size='sm'
/>
</Td>
</Tr>
))}
</Tbody>
</Table>
);
}

Styling

  • Icon: DownloadSolid with white fill
  • Size: Consistent with theme sizing
  • Tooltip: Arrow tooltip with label text

FilterButton

A specialized icon button for filter actions (similar to DownloadButton but for filtering).

Component Location

import FilterButton from 'components/Button/FilterButton';

Props

PropTypeRequiredDefaultDescription
labelstring-Aria-label and tooltip text
sizestring-'sm'Button size
...restobject--Additional IconButton props

TypeScript Interface

interface FilterButtonProps {
label: string;
size?: string;
[key: string]: any;
}

Features

Filter Icon

  • Pre-configured with DownloadSolid icon (note: this appears to be a copy of DownloadButton)
  • White fill color for visibility
  • Consistent 20px sizing

Usage Examples

Basic Filter Button

import FilterButton from 'components/Button/FilterButton';

function DataFilter() {
const handleFilter = () => {
openFilterPanel();
};

return <FilterButton label='Filter data' onClick={handleFilter} />;
}

Styling

  • Icon: DownloadSolid with white fill (should be filter icon)
  • Size: Consistent with theme sizing
  • Tooltip: Arrow tooltip with label text

ButtonRightIcon

A button component with right-side icon and loading state management.

Component Location

import ButtonRightIcon from 'components/Button/ButtonRightIcon';

Props

PropTypeRequiredDefaultDescription
textstring-Button text
iconReactNode-Icon element to display
isLoadingboolean-falseLoading state
spinnerColorstring-'white'Spinner color during loading
loadingTextstring-''Text to show during loading
...restobject--Additional Button props

TypeScript Interface

interface ButtonRightIconProps {
text: string;
icon: React.ReactNode;
isLoading?: boolean;
spinnerColor?: string;
loadingText?: string;
[key: string]: any;
}

Features

Loading State Management

  • Automatic spinner replacement during loading
  • Configurable spinner color
  • Optional loading text
  • Proper disabled state handling

Icon Integration

  • Right-side icon placement
  • Icon replacement with spinner during loading
  • Consistent styling with theme variants

Usage Examples

Basic Button with Icon

import ButtonRightIcon from 'components/Button/ButtonRightIcon';
import { SaveSolid } from 'components/WPIcons';

function SaveButton() {
const handleSave = () => {
saveData();
};

return (
<ButtonRightIcon
text='Save'
icon={<SaveSolid />}
onClick={handleSave}
colorScheme='green'
/>
);
}

Button with Loading State

import ButtonRightIcon from 'components/Button/ButtonRightIcon';
import { UploadSolid } from 'components/WPIcons';

function UploadButton() {
const [isUploading, setIsUploading] = useState(false);

const handleUpload = async () => {
setIsUploading(true);
try {
await uploadFile();
} finally {
setIsUploading(false);
}
};

return (
<ButtonRightIcon
text='Upload'
icon={<UploadSolid />}
isLoading={isUploading}
loadingText='Uploading...'
spinnerColor='white'
onClick={handleUpload}
/>
);
}

Form Submit Button

import ButtonRightIcon from 'components/Button/ButtonRightIcon';
import { CheckSolid } from 'components/WPIcons';

function SubmitButton({ isSubmitting, onSubmit }) {
return (
<ButtonRightIcon
text='Submit'
icon={<CheckSolid />}
isLoading={isSubmitting}
loadingText='Submitting...'
onClick={onSubmit}
type='submit'
colorScheme='blue'
/>
);
}

Different Button Variants

import ButtonRightIcon from 'components/Button/ButtonRightIcon';
import { ExternalLinkSolid } from 'components/WPIcons';

function ActionButtons() {
return (
<VStack spacing={3}>
<ButtonRightIcon
text='Primary Action'
icon={<ExternalLinkSolid />}
variant='solid'
colorScheme='blue'
/>
<ButtonRightIcon
text='Secondary Action'
icon={<ExternalLinkSolid />}
variant='outline'
colorScheme='blue'
/>
<ButtonRightIcon
text='Ghost Action'
icon={<ExternalLinkSolid />}
variant='ghost'
colorScheme='blue'
/>
</VStack>
);
}

Styling

  • Variants: Supports all Chakra UI Button variants
  • Disabled State: Opacity 0.4, not-allowed cursor
  • Loading State: Spinner replacement with configurable color
  • Icon Position: Right side of button text

Button Patterns

Action Button Groups

import {
WPExportAction,
WPFilterAction,
CustomIconButton,
} from 'components/Button';
import { RefreshSolid } from 'components/WPIcons';

function TableActions() {
return (
<HStack spacing={2}>
<WPFilterAction handleClick={openFilter} />
<WPExportAction handleClick={exportData} />
<CustomIconButton
icon={<RefreshSolid />}
label='Refresh data'
onClick={refreshData}
/>
</HStack>
);
}

Conditional Button Display

import { CustomIconButton, ButtonRightIcon } from 'components/Button';
import { EditSolid, SaveSolid } from 'components/WPIcons';

function ConditionalButtons({ isEditing, onEdit, onSave }) {
if (isEditing) {
return (
<ButtonRightIcon
text='Save Changes'
icon={<SaveSolid />}
onClick={onSave}
colorScheme='green'
/>
);
}

return (
<CustomIconButton icon={<EditSolid />} label='Edit item' onClick={onEdit} />
);
}

Loading State Patterns

import { ButtonRightIcon, DownloadButton } from 'components/Button';

function LoadingButtons() {
const [states, setStates] = useState({
downloading: false,
processing: false,
});

return (
<HStack spacing={4}>
<DownloadButton
label='Download file'
isLoading={states.downloading}
onClick={() => handleDownload()}
/>
<ButtonRightIcon
text='Process'
icon={<ProcessSolid />}
isLoading={states.processing}
loadingText='Processing...'
onClick={() => handleProcess()}
/>
</HStack>
);
}

Best Practices

Button Selection

  1. WPExportAction: Use for data export functionality
  2. WPFilterAction: Use for opening filter panels
  3. CustomIconButton: Use for flexible icon actions
  4. DownloadButton: Use for file download actions
  5. ButtonRightIcon: Use for buttons with icons and loading states

Accessibility

  1. Labels: Always provide descriptive labels
  2. Tooltips: Use tooltips for icon-only buttons
  3. Keyboard Navigation: Ensure buttons are keyboard accessible
  4. Screen Readers: Provide proper aria-labels

Performance

  1. Icon Optimization: Use optimized SVG icons
  2. Event Handlers: Memoize event handlers when possible
  3. Loading States: Provide immediate feedback for actions
  4. Disabled States: Prevent multiple clicks during operations

Testing

import { render, screen, fireEvent } from '@testing-library/react';
import WPExportAction from 'components/Button/WPExportAction';

describe('Button Components', () => {
it('should call handleClick when export button is clicked', () => {
const handleClick = jest.fn();
render(<WPExportAction handleClick={handleClick} />);

fireEvent.click(screen.getByText('Export'));
expect(handleClick).toHaveBeenCalledTimes(1);
});

it('should show loading state in ButtonRightIcon', () => {
render(
<ButtonRightIcon
text='Submit'
icon={<span>icon</span>}
isLoading={true}
loadingText='Loading...'
/>,
);

expect(screen.getByText('Loading...')).toBeInTheDocument();
});
});

This comprehensive button system provides consistent, accessible, and branded button components for all common actions in the WorkPayCore Frontend application.