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.