Data Table
A dashboard table with search, sorting, selection, and pagination.
Overview
Data Table composes Table, Checkbox, Input, Dropdown Menu, Skeleton, and Pagination into a client-side data view. Mark columns as sortable or searchable, then opt into selection, visibility, and pagination as needed.
Preview
| Status | ||
|---|---|---|
| Vinyaas | Sarang | Active |
| Dashboard | Priya | Review |
| Mobile App | Aarav | Complete |
Showing 1–3 of 8
Customize
Installation
Add the component with the CLI. It copies the files in and installs anything they depend on.
npx vinyaas add data-tableUsage
import { DataTable, type DataTableColumn } from "@/components/ui/data-table";
type Project = {
id: string;
name: string;
owner: string;
status: string;
};
const columns: DataTableColumn<Project>[] = [
{
id: "name",
header: "Project",
accessorKey: "name",
sortable: true,
searchable: true,
enableHiding: false,
},
{
id: "owner",
header: "Owner",
accessorKey: "owner",
sortable: true,
searchable: true,
},
{
id: "status",
header: "Status",
accessorKey: "status",
},
];
export function ProjectsTable({ data }: { data: Project[] }) {
return (
<DataTable
columns={columns}
data={data}
searchable
searchPlaceholder="Search projects..."
selectable
columnVisibility
pagination={5}
/>
);
}Examples
Basic
Columns and rows from a typed dataset.
| Status | ||
|---|---|---|
| Vinyaas | Sarang | Active |
| Dashboard | Priya | Review |
| Mobile App | Aarav | Complete |
Sorting
Click a sortable header to cycle ascending, descending, and unsorted. The sort icon has a fixed size and the table layout is fixed, so columns keep their width while the order changes.
| Status | ||
|---|---|---|
| Vinyaas | Sarang | Active |
| Dashboard | Priya | Review |
| Mobile App | Aarav | Complete |
| Marketing | Ananya | Draft |
Selection
Select rows individually or use the header checkbox for the visible page.
| Status | |||
|---|---|---|---|
| Vinyaas | Sarang | Active | |
| Dashboard | Priya | Review | |
| Mobile App | Aarav | Complete | |
| Marketing | Ananya | Draft |
Search
Filter rows across columns marked searchable.
| Status | ||
|---|---|---|
| Vinyaas | Sarang | Active |
| Dashboard | Priya | Review |
| Mobile App | Aarav | Complete |
| Marketing | Ananya | Draft |
| Analytics | Sarang | Active |
| Billing | Priya | Draft |
| Onboarding | Aarav | Review |
| Docs Site | Ananya | Active |
Rows per page
pageSizeOptions renders a toggle group beside the pager, so the reader picks how many rows a page holds. pagination still sets the starting size.
| Status | ||
|---|---|---|
| Vinyaas | Sarang | Active |
| Dashboard | Priya | Review |
| Mobile App | Aarav | Complete |
Showing 1–3 of 8
Loading
Skeleton rows while data is loading.
| Status | ||
|---|---|---|
Empty
A clear empty state when nothing matches.
| Status | ||
|---|---|---|
| No results found. | ||
In practice
A projects board with search, selection, column visibility, pagination, status badges, and row actions.
| Status | Actions | ||||
|---|---|---|---|---|---|
| Vinyaas | Sarang | Active | 2m ago | ||
| Dashboard | Priya | Review | 1h ago | ||
| Mobile App | Aarav | Complete | 2d ago | ||
| Marketing | Ananya | Draft | 4d ago |
Showing 1–4 of 8
API
Other attributes for the underlying element are passed through.
| Name | Type | Default | Description |
|---|---|---|---|
columns | DataTableColumn<T>[] | — | Column definitions for headers, cells, sorting, and search. |
data | T[] | — | Row data rendered by the table. |
getRowId | (row: T, index: number) => string | — | Stable row id. Defaults to row.id when present. |
searchable | boolean | false | Shows a search field over searchable columns. |
searchPlaceholder | string | "Search…" | Placeholder and accessible name for the search field. |
selectable | boolean | false | Adds row checkboxes and a select-all control. |
pagination | boolean | number | false | Client-side pagination. A number sets the page size. |
pageSizeOptions | number[] | — | Row-count choices offered beside the pager as a toggle group. Needs pagination, and is hidden below two choices. Picking one returns to page 1. |
pageSizeLabel | string | "Rows per page" | Names the row-count toggle group. |
actionsWidth | string | number | "7rem" | Width of the trailing actions column. |
columns[].width | string | number | — | Column width. The table uses a fixed layout, so sorting, paging, and search never resize columns. Columns without a width share the remaining space. |
columnVisibility | boolean | false | Shows a Columns menu to hide and show columns. |
loading | boolean | false | Renders skeleton rows instead of data. |
emptyMessage | string | "No results found." | Copy shown when there are no rows to display. |
renderRowActions | (row: T) => ReactNode | — | Optional trailing actions column renderer. |
Accessibility
The table keeps semantic table markup. Sortable headers are buttons with aria-sort on the column header. Selection checkboxes include accessible names for individual rows and select-all, including the partial-selection state.
- Enter and Space activate sortable headers and row actions.
- Pagination reuses the accessible Pagination controls.
- Column visibility items are menuitem checkboxes.
- Loading and empty states do not leave orphaned interactive controls.