TablePro
Tables display data in rows and columns with support for sorting, row selection, pagination, and infinite scroll. The modular structure allows flexible composition of headers, cells, toolbars, and pagination.
Table Playground
Installation
You can add the table component to your project manually:
Install the following dependencies:
npm install class-variance-authority clsx tailwind-merge @phosphor-icons/react @react-aria/button @react-aria/focus @react-aria/interactions @react-aria/progress @react-aria/utilsCopy and paste the following code into your project.
Update the import paths to match your project setup.
Update the import aliases (e.g. @/components, @/utils) in the copied files to match your project's path configuration.
Basic Usage
A simple table with header and data rows:
<Table>
<TableHeader>
<TableRow>
<TableHeaderCell>Name</TableHeaderCell>
<TableHeaderCell>Email</TableHeaderCell>
<TableHeaderCell>Role</TableHeaderCell>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableRowCell>John Doe</TableRowCell>
<TableRowCell>john@example.com</TableRowCell>
<TableRowCell>Admin</TableRowCell>
</TableRow>
</TableBody>
</Table>Density
Two density options are available — default (56px rows) and compact (48px rows):
<Table density="default">...</Table>
<Table density="compact">...</Table>Sorting
Enable sorting on columns with sortable prop and handle sort state:
const [sortColumn, setSortColumn] = useState<string | null>(null);
const [sortDirection, setSortDirection] = useState<'asc' | 'desc' | null>(null);
const handleSort = (column: string) => {
if (sortColumn === column) {
if (sortDirection === 'asc') setSortDirection('desc');
else if (sortDirection === 'desc') { setSortColumn(null); setSortDirection(null); }
else setSortDirection('asc');
} else {
setSortColumn(column);
setSortDirection('asc');
}
};
<Table sortColumn={sortColumn} sortDirection={sortDirection} onSort={handleSort}>
<TableHeader>
<TableRow>
<TableHeaderCell columnKey="name" sortable>Name</TableHeaderCell>
<TableHeaderCell columnKey="email" sortable>Email</TableHeaderCell>
</TableRow>
</TableHeader>
...
</Table>Row Selection
Enable row selection with checkboxes:
const [selectedIds, setSelectedIds] = useState<string[]>([]);
<Table
selectedIds={selectedIds}
onSelectionChange={setSelectedIds}
allRowIds={data.map(r => r.id)}
>
<TableHeader>
<TableRow>
<TableHeaderCell type="checkbox" />
<TableHeaderCell>Name</TableHeaderCell>
</TableRow>
</TableHeader>
<TableBody>
{data.map(row => (
<TableRow key={row.id} rowId={row.id}>
<TableRowCell type="checkbox" />
<TableRowCell>{row.name}</TableRowCell>
</TableRow>
))}
</TableBody>
</Table>Toolbar
Add a toolbar with title, search, filters, and action button:
<TableToolbar
title="Users"
count={100}
showSearch
searchValue={searchValue}
onSearchChange={setSearchValue}
showFilters
onFilterClick={() => console.log('Filters clicked')}
showButton
buttonText="Add User"
onButtonClick={() => console.log('Add clicked')}
/>Pagination
Add pagination controls below the table:
<Pagination
currentPage={1}
totalItems={100}
pageSize={10}
onPageChange={(page) => console.log('Page:', page)}
onPageSizeChange={(size) => console.log('Size:', size)}
pageSizeOptions={[10, 25, 50, 100]}
/>Infinite Scroll
Enable infinite scroll with the loadingStrategy prop:
<Table loadingStrategy="infinite">
<TableBody
hasMore={hasMore}
loadingMore={isLoading}
onLoadMore={loadMoreData}
>
{data.map(row => (
<TableRow key={row.id}>...</TableRow>
))}
</TableBody>
</Table>Sticky Header
Keep the header visible when scrolling:
<div style={{ maxHeight: 400 }}>
<Table stickyHeader>
...
</Table>
</div>Accessibility
The Table components are fully accessible:
- Keyboard navigation: Tab through interactive cells, Enter/Space to toggle selection
- Screen readers: Proper
role="grid"with column headers and row structure - Sort announcements: Sort direction announced via
aria-sort - Selection state: Checkbox states properly announced
Table Props
| Prop | Type | Default | Description |
|---|---|---|---|
density | 'default' | 'compact' | 'default' | Row height density. |
selectedIds | string[] | [] | Array of selected row IDs. |
onSelectionChange | (ids: string[]) => void | — | Callback when selection changes. |
sortColumn | string | null | null | Currently sorted column key. |
sortDirection | 'asc' | 'desc' | null | null | Current sort direction. |
onSort | (column: string, direction: ...) => void | — | Callback when sort changes. |
loading | boolean | false | Loading state. |
loadingStrategy | 'pagination' | 'infinite' | 'pagination' | Loading strategy. |
stickyHeader | boolean | false | Keep header visible when scrolling. |
standalone | boolean | false | Add border/radius when used without wrapper. |
allRowIds | string[] | [] | All row IDs for select-all functionality. |
TableHeaderCell Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'text' | 'checkbox' | 'text' | Cell type. |
columnKey | string | — | Column key for sorting. |
sortable | boolean | false | Enable sorting on this column. |
align | 'left' | 'center' | 'right' | 'left' | Text alignment. |
width | number | string | — | Column width. |
minWidth | number | string | — | Minimum column width. |
TableRowCell Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'text' | 'checkbox' | 'text' | Cell type. |
align | 'left' | 'center' | 'right' | 'left' | Text alignment. |
truncate | boolean | false | Truncate long text with ellipsis. |
TableToolbar Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | 'Items' | Toolbar title. |
count | number | — | Item count to display in badge. |
showTitleBadge | boolean | true | Show count badge. |
showSearch | boolean | true | Show search input. |
searchPlaceholder | string | 'Search task, project...' | Search placeholder. |
searchValue | string | — | Controlled search value. |
onSearchChange | (value: string) => void | — | Search change callback. |
showFilters | boolean | true | Show filter button. |
onFilterClick | () => void | — | Filter button callback. |
showButton | boolean | true | Show action button. |
buttonText | string | 'Add Task' | Action button text. |
onButtonClick | () => void | — | Action button callback. |
actions | ReactNode | — | Custom actions slot. |
Pagination Props
| Prop | Type | Default | Description |
|---|---|---|---|
currentPage | number | 1 | Current page number. |
totalItems | number | 0 | Total number of items. |
pageSize | number | 10 | Items per page. |
onPageChange | (page: number) => void | — | Page change callback. |
onPageSizeChange | (size: number) => void | — | Page size change callback. |
pageSizeOptions | number[] | [10, 25, 50, 100] | Available page sizes. |


