Data tables are the primary mechanism for organizing and displaying complex sets of data. They allow users to scan, sort, filter, and compare information efficiently.
Primary use cases:
- Managing large lists (e.g., Artist roster, Campaign plans, User management, Artist's tracks).
- Comparing metrics across multiple entities (e.g., Track performance).
- Reviewing line-item details (e.g., Transaction history).
Table is built on top of TanStack Table.
All Tables are rendered with TanStack Table and the following columns and data defaults:
const columns = [
columnHelper.accessor('name', {
id: 'name',
header: 'Name',
}),
columnHelper.accessor('email', {
id: 'email',
header: 'Email',
}),
];
const data = [
{ id: '1', name: 'John Doe', email: 'john@example.com' },
{ id: '2', name: 'Jane Doe', email: 'jane@example.com' },
];
Basic Table
A barebones table containing text data.
| Name | |
|---|---|
| John Doe | john@example.com |
| Jane Doe | jane@example.com |
Code snippet
<Table
columns={[
{
accessorKey: 'name',
enableSorting: false,
header: 'Name',
id: 'name'
},
{
accessorKey: 'email',
enableSorting: false,
header: 'Email',
id: 'email'
}
]}
data={[
{
email: 'john@example.com',
id: '1',
name: 'John Doe'
},
{
email: 'jane@example.com',
id: '2',
name: 'Jane Doe'
}
]}
onSortingChange={function f0e(){}}
/>
Striped Table
Most use cases will likely set variant to "striped" to improve readability.
| Name | |
|---|---|
| John Doe | john@example.com |
| Jane Doe | jane@example.com |
Code snippet
<Table
columns={[
{
accessorKey: 'name',
enableSorting: false,
header: 'Name',
id: 'name'
},
{
accessorKey: 'email',
enableSorting: false,
header: 'Email',
id: 'email'
}
]}
data={[
{
email: 'john@example.com',
id: '1',
name: 'John Doe'
},
{
email: 'jane@example.com',
id: '2',
name: 'Jane Doe'
}
]}
onSortingChange={function f0e(){}}
variant="striped"
/>
Loading Skeletons
Pass isLoading as true to show the default loading skeletons for Table. Customize how many rows show up with loadingRowCount.
| Name | |
|---|---|
Code snippet
<Table
columns={[
{
accessorKey: 'name',
enableSorting: false,
header: 'Name',
id: 'name'
},
{
accessorKey: 'email',
enableSorting: false,
header: 'Email',
id: 'email'
}
]}
data={[]}
isLoading
loadingRowCount={3}
onSortingChange={function f0e(){}}
/>
Displaying No Content
By default, a table with no content will show a single row saying "No data".
| Name | |
|---|---|
| No data | |
Code snippet
<Table
columns={[
{
accessorKey: 'name',
enableSorting: false,
header: 'Name',
id: 'name'
},
{
accessorKey: 'email',
enableSorting: false,
header: 'Email',
id: 'email'
}
]}
data={[]}
onSortingChange={function f0e(){}}
/>
Customize this content by passing in a component to EmptyContent.
| Name | |
|---|---|
| Empty | |
Code snippet
<Table
EmptyContent={function f0e(){}}
columns={[
{
accessorKey: 'name',
enableSorting: false,
header: 'Name',
id: 'name'
},
{
accessorKey: 'email',
enableSorting: false,
header: 'Email',
id: 'email'
}
]}
data={[]}
onSortingChange={function f0e(){}}
/>
Sorting
The table headers support showing sorting information on columns where enableSorting is set to true.
Sortable (unsorted)
| Name | |
|---|---|
| John Doe | john@example.com |
| Jane Doe | jane@example.com |
Code snippet
<Table
columns={[
{
accessorKey: 'name',
enableSorting: true,
header: 'Name',
id: 'name',
sortingFn: 'alphanumeric'
},
{
accessorKey: 'email',
enableSorting: true,
header: 'Email',
id: 'email',
sortingFn: 'alphanumeric'
}
]}
data={[
{
email: 'john@example.com',
id: '1',
name: 'John Doe'
},
{
email: 'jane@example.com',
id: '2',
name: 'Jane Doe'
}
]}
onSortingChange={function f0e(){}}
/>
Sorted by Name — Ascending
| Name | |
|---|---|
| Jane Doe | jane@example.com |
| John Doe | john@example.com |
Code snippet
<Table
columns={[
{
accessorKey: 'name',
enableSorting: true,
header: 'Name',
id: 'name',
sortingFn: 'alphanumeric'
},
{
accessorKey: 'email',
enableSorting: true,
header: 'Email',
id: 'email',
sortingFn: 'alphanumeric'
}
]}
data={[
{
email: 'jane@example.com',
id: '2',
name: 'Jane Doe'
},
{
email: 'john@example.com',
id: '1',
name: 'John Doe'
}
]}
onSortingChange={function f0e(){}}
sort={[{desc: false, id: 'name'}]}
/>
Sorted by Name — Descending
| Name | |
|---|---|
| John Doe | john@example.com |
| Jane Doe | jane@example.com |
Code snippet
<Table
columns={[
{
accessorKey: 'name',
enableSorting: true,
header: 'Name',
id: 'name',
sortingFn: 'alphanumeric'
},
{
accessorKey: 'email',
enableSorting: true,
header: 'Email',
id: 'email',
sortingFn: 'alphanumeric'
}
]}
data={[
{
email: 'john@example.com',
id: '1',
name: 'John Doe'
},
{
email: 'jane@example.com',
id: '2',
name: 'Jane Doe'
}
]}
onSortingChange={function f0e(){}}
sort={[{desc: true, id: 'name'}]}
/>
Sorting can happen client-side or server-side. Most sorting is expected to be handled server-side. Use the manualSorting, onSortingChange, and sorting props to control the sorting state of the Table.
Using the Component Parts Individually
The Table component uses a bunch of pieces under the hood. You can build out your own table using those pieces to get significantly more flexibility at the cost of manual maintenance.
| Name | |
|---|---|
| John Doe | john@example.com |
| Jane Doe | jane@example.com |
Code snippet
{
render() {
const table = useReactTable({
data: [{
id: '1',
name: 'John Doe',
email: 'john@example.com'
}, {
id: '2',
name: 'Jane Doe',
email: 'jane@example.com'
}],
columns,
getCoreRowModel: getCoreRowModel()
});
return <Table.Table table={table}>
<Table.Head>
{table.getHeaderGroups().map(headerGroup => <Table.Row key={headerGroup.id}>
{headerGroup.headers.map(header => <Table.HeadCell key={header.id} header={header} />)}
</Table.Row>)}
</Table.Head>
<Table.Body>
<Table.Row>
<Table.Cell>John Doe</Table.Cell>
<Table.Cell>john@example.com</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>Jane Doe</Table.Cell>
<Table.Cell>jane@example.com</Table.Cell>
</Table.Row>
</Table.Body>
</Table.Table>;
}
}