Data Table
Data Display
Stablev1.0.0
Sortable, filterable data table with infinite scroll and TanStack Query integration, built on Ariakit for accessibility.
Preview
ProductsName Price Product A $10 Product B $20
Installation
pnpm add @component-labs/uiUsage
import { DataTable } from "@component-labs/ui";
<DataTable
data={items}
label="Products"
tableHeader={<tr><th>Name</th><th>Price</th></tr>}
tableRow={(item) => <tr><td>{item.name}</td><td>{item.price}</td></tr>}
/>Props
| Name | Type | Default | Description |
|---|---|---|---|
data* | T[] | - | Array of data items to display in the table |
label* | string | - | Accessible label for the table |
tableHeader* | ReactElement | - | Table header component |
tableRow* | (item: T, index: number) => ReactElement | - | Function to render each table row |
description | string | - | Optional description for assistive technology |
loadingRow | ReactElement | - | Skeleton row component shown during loading |
emptyRow | ReactElement | - | Component shown when no data is available |
tableFooter | ReactElement | - | Optional table footer component |
pageLimit | number | 10 | Number of skeleton rows to show during loading |
isLoading | boolean | false | Initial loading state |
hasNextPage | boolean | false | Whether there are more pages to fetch |
fetchNextPage | () => void | - | Callback to fetch the next page |
isFetchingNextPage | boolean | false | Whether currently fetching next page |
isError | boolean | false | Error state - prevents infinite retry loops |
triggerOffset | number | 5 | Number of rows from end to trigger fetchNextPage |
rootMargin | string | '200px' | IntersectionObserver rootMargin |
Examples
Basic Table
Simple data table with static data
const products = [
{ id: 1, name: "Product A", price: "$10" },
{ id: 2, name: "Product B", price: "$20" },
];
<DataTable
data={products}
label="Products"
tableHeader={
<tr>
<th>Name</th>
<th>Price</th>
</tr>
}
tableRow={(product) => (
<tr key={product.id}>
<td>{product.name}</td>
<td>{product.price}</td>
</tr>
)}
/>With Infinite Scroll
Infinite scroll with TanStack Query
const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
useInfiniteQuery({ ... });
<DataTable
data={data?.pages.flatMap(p => p.items) ?? []}
label="Items"
isLoading={isLoading}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
isFetchingNextPage={isFetchingNextPage}
tableHeader={<tr><th>Name</th></tr>}
tableRow={(item) => <tr><td>{item.name}</td></tr>}
loadingRow={<tr><td><Skeleton /></td></tr>}
/>With Empty State
Custom empty state when no data
<DataTable
data={[]}
label="Users"
tableHeader={<tr><th>Name</th><th>Email</th></tr>}
tableRow={(user) => <tr><td>{user.name}</td><td>{user.email}</td></tr>}
emptyRow={
<div className="text-center py-8">
<p>No users found</p>
<Button onClick={addUser}>Add User</Button>
</div>
}
/>Performance
Bundle Size
~6kB gzipped
Minified and gzipped
Dependencies
- •@ariakit/react
Accessibility
- •Built on Ariakit's Composite component for keyboard navigation
- •Proper ARIA table roles (table, row, cell, rowgroup)
- •Screen reader announcements for loading states
- •Accessible labels and descriptions
- •Keyboard navigation between cells
- •Live region announcements for data changes