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
- WPExportAction - Export button with upload icon
- WPFilterAction - Filter button with filter icon
- ButtonRightIcon - Button with right icon and loading state
Icon Buttons
- CustomIconButton - Customizable icon button with tooltip
- DownloadButton - Download icon button with tooltip
- FilterButton - Filter icon button with tooltip
WPExportAction
A specialized button for export actions with consistent styling and upload icon.
Component Location
import WPExportAction from 'components/Button/WPExportAction';
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| handleClick | function | ✓ | - | Click handler for export action |
| size | string | - | 'sm' | Button size |
| ...props | ButtonProps | - | - | 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'>
<Heading>Employee Data</Heading>
<WPExportAction handleClick={handleExport} />
</HStack>
<Table>{/* Table content */}</Table>
</VStack>
);
}
Custom Size Export Button
import WPExportAction from 'components/Button/WPExportAction';
function ReportsPage() {
const handleExportReport = () => {
generateReport();
};
return (
<Card>
<CardHeader>
<HStack justify='space-between'>
<Heading size='md'>Monthly Report</Heading>
<WPExportAction handleClick={handleExportReport} size='md' />
</HStack>
</CardHeader>
<CardBody>
<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
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| handleClick | function | ✓ | - | Click handler for filter action |
| size | string | - | 'sm' | Button size |
| ...props | ButtonProps | - | - | 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 (
<VStack>
<HStack justify='space-between'>
<Heading>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 (
<HStack>
<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
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| icon | ReactNode | ✓ | - | Icon element to display |
| label | string | ✓ | - | Aria-label and tooltip text |
| size | string | - | 'sm' | Button size |
| noTooltip | boolean | - | false | Disable tooltip display |
| ...rest | object | - | - | 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
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| label | string | ✓ | - | Aria-label and tooltip text |
| size | string | - | 'sm' | Button size |
| ...rest | object | - | - | 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 (
<Table>
<Thead>
<Tr>
<Th>Name</Th>
<Th>Size</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{files.map(file => (
<Tr key={file.id}>
<Td>{file.name}</Td>
<Td>{file.size}</Td>
<Td>
<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
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| label | string | ✓ | - | Aria-label and tooltip text |
| size | string | - | 'sm' | Button size |
| ...rest | object | - | - | 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
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| text | string | ✓ | - | Button text |
| icon | ReactNode | ✓ | - | Icon element to display |
| isLoading | boolean | - | false | Loading state |
| spinnerColor | string | - | 'white' | Spinner color during loading |
| loadingText | string | - | '' | Text to show during loading |
| ...rest | object | - | - | 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
- WPExportAction: Use for data export functionality
- WPFilterAction: Use for opening filter panels
- CustomIconButton: Use for flexible icon actions
- DownloadButton: Use for file download actions
- ButtonRightIcon: Use for buttons with icons and loading states
Accessibility
- Labels: Always provide descriptive labels
- Tooltips: Use tooltips for icon-only buttons
- Keyboard Navigation: Ensure buttons are keyboard accessible
- Screen Readers: Provide proper aria-labels
Performance
- Icon Optimization: Use optimized SVG icons
- Event Handlers: Memoize event handlers when possible
- Loading States: Provide immediate feedback for actions
- 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.