# Data Table
URL: /docs/web/components/data-table
A lightweight, read-only TanStack table for Docyrus data sources with value renderers, row selection, grouping, and optional pagination.
**Demo:**
```tsx
'use client';
// @custom-demo
import { useMemo, useState } from 'react';
import {
getCoreRowModel,
getExpandedRowModel,
getFilteredRowModel,
getGroupedRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
type ColumnDef,
type ExpandedState,
type GroupingState,
type PaginationState,
type RowSelectionState,
type SortingState
} from '@tanstack/react-table';
import {
Building2,
Mail,
MoreHorizontal,
Phone,
Pencil,
Plus,
Trash2
} from 'lucide-react';
import {
DataGridGroupMenu,
DataGridSortMenu
} from '@docyrus/ui/components/data-grid';
import { DataTable, getDataTableSelectColumn } from '@docyrus/ui/components/data-table';
import { IdentityValue } from '@docyrus/ui/components/value-renderers/identity-value';
import { StatusValue } from '@docyrus/ui/components/value-renderers/status-value';
import { TextValue } from '@docyrus/ui/components/value-renderers/text-value';
import { UserValue } from '@docyrus/ui/components/value-renderers/user-value';
import { Button } from '@docyrus/ui/primitives/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger
} from '@docyrus/ui/primitives/ui/dropdown-menu';
import { Input } from '@docyrus/ui/primitives/ui/input';
import { TooltipProvider } from '@docyrus/ui/primitives/ui/tooltip';
import { cn } from '@docyrus/ui/primitives/lib/utils';
import { PropControls, type PropControl } from '@/components/prop-controls';
type CompanyRow = {
id: string;
name: string;
owner: string;
ownerAvatar?: string;
ownerInitials?: string;
status: 'active' | 'onboarding' | 'paused';
phone: string;
email: string;
city: string;
segment: string;
};
const ROWS: Array
)
}
], [enableRowNumbers]);
const filteredData = useMemo(() => {
const needle = keyword.trim().toLowerCase();
if (!needle) return ROWS;
return ROWS.filter(row => [
row.name,
row.owner,
row.email,
row.city,
row.segment,
row.status
].some(value => value.toLowerCase().includes(needle)));
}, [keyword]);
const table = useReactTable({
data: filteredData,
columns,
state: {
sorting,
rowSelection,
grouping,
expanded,
pagination: enablePagination ? pagination : {
pageIndex: 0,
pageSize: Number.MAX_SAFE_INTEGER
}
},
onSortingChange: setSorting,
onRowSelectionChange: setRowSelection,
onGroupingChange: setGrouping,
onExpandedChange: setExpanded,
onPaginationChange: setPagination,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getGroupedRowModel: getGroupedRowModel(),
getExpandedRowModel: getExpandedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
enableRowSelection: true,
autoResetPageIndex: false
});
const controls: Array
);
}
```
## When To Use
Use `DataTable` when you want the Docyrus field rendering layer and saved-view ergonomics without the heavier editable spreadsheet behavior of `DataGrid`.
- Read-only rendering only
- Standard HTML table layout using the shadcn `Table` primitive
- Works with TanStack sorting, grouping, selection, and pagination
- Lets app developers compose their own toolbar and surrounding UI freely
`DataTable` intentionally does **not** provide editable cells, display mode switching, row-height controls, paste support, or grid-style keyboard navigation.
## Usage
```tsx
import {
DataTable,
getDataTableSelectColumn
} from '@docyrus/ui/components/data-table';
import {
DataGridGroupMenu,
DataGridSortMenu
} from '@docyrus/ui/components/data-grid';
import {
getCoreRowModel,
getExpandedRowModel,
getGroupedRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
type ColumnDef
} from '@tanstack/react-table';
const columns: Array> = [
getDataTableSelectColumn({ enableRowNumbers: true }),
{
accessorKey: 'name',
header: 'Company'
},
{
accessorKey: 'status',
header: 'Status',
meta: { groupable: true }
}
];
function MyTable({ data }: { data: Array }) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getGroupedRowModel: getGroupedRowModel(),
getExpandedRowModel: getExpandedRowModel(),
getPaginationRowModel: getPaginationRowModel()
});
return (
);
}
```
## `useDocyrusDataTable`
For Docyrus data-source screens, use the hook to combine field metadata, value renderers, saved views, remote loading, and toolbar controls.
```tsx
import { DataTable } from '@docyrus/ui/components/data-table';
import { useDocyrusDataTable } from '@docyrus/ui/hooks/use-docyrus-data-table';
function OrganizationsTable() {
const {
table,
tableProps,
toolbar,
sidePanel
} = useDocyrusDataTable({
client,
appSlug: 'base',
dataSourceSlug: 'organization',
collection,
users
});
return (
);
}
```
## Features
- `getDataTableSelectColumn()` supports checkbox selection and optional row numbers in the select column.
- Grouped rows render inline with expand/collapse controls and group counts.
- Identity values can render in compact UUID mode with tooltip + copy affordance.
- `useDocyrusDataTable()` reuses Docyrus saved views, search, filter, sort, grouping, export, and paging behavior.
## API Notes
### `DataTable`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `table` | `Table` | — | TanStack table instance |
| `emptyText` | `string` | `'No results.'` | Empty state label |
| `isLoading` | `boolean` | `false` | Shows loading row state |
| `pagination` | `boolean` | `false` | Renders the standard pagination footer |
| `containerClassName` | `string` | — | Wrapper border/container styling |
| `rowClassName` | `string \| (row) => string` | — | Per-row styling hook |
### `getDataTableSelectColumn`
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enableRowNumbers` | `boolean` | `false` | Shows row numbers when the row is not selected |
| `size` | `number` | `44` | Fixed select-column width |
### `useDocyrusDataTable`
The hook mirrors the lightweight table workflow:
- returns `table`, `tableProps`, `toolbar`, `sidePanel`, `items`, `resolvedListParams`, `pagingMode`, and `reload`
- supports `mapColumn`, `extraColumns`, `actionsColumn`, `showSelectColumn`, `enableRowNumbers`, and toolbar content slots
- stays read-only by design