# Data table

> Sorting, search, filters, selection, bulk actions, column visibility, pagination, expandable rows, export and mobile cards.

Component · Pro · https://lodeui.com/components/data-table

## When to use

- Records people sort, filter, select and act on: users, invoices, orders.

## When not to use

- A few rows with no actions: a plain table is enough.
- Spreadsheet editing.

## Installation

```bash
npx shadcn@latest add @lode/data-table
```

Pro: needs a Lode API key and the `@lode` registry in components.json. See https://lodeui.com/docs/cli.

npm dependencies: motion, lucide-react

## Usage

```tsx title="example.tsx"
import { DataTable, type Column } from "@/components/ui/data-table";

type Invoice = { id: string; customer: string; amount: number; status: string };

const columns: Column<Invoice>[] = [
  { key: "customer", header: "Customer", accessor: (r) => r.customer, sortable: true, primary: true },
  { key: "status", header: "Status", accessor: (r) => r.status, filterable: true },
  { key: "amount", header: "Amount", accessor: (r) => r.amount, sortable: true, align: "right", cell: (r) => `$${r.amount}` },
];

export function Invoices({ data }: { data: Invoice[] }) {
  return <DataTable data={data} columns={columns} getRowId={(r) => r.id} selectable exportName="invoices" />;
}
```

## API reference

### DataTable

Sorting, search, filters, selection with bulk actions, column visibility, pagination, expandable rows, CSV export and keyboard navigation. Becomes cards below 640px.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| data / columns / getRowId | `T[] / Column<T>[] / (row) => string` | – | Rows, column definitions and a stable id. |
| pageSize | `number` | `10` | Rows per page. |
| selectable / bulkActions | `boolean / { label; icon?; destructive?; onRun(rows) }[]` | – | Row checkboxes and actions on the selection. |
| rowActions / renderDetail / onRowClick | `(row) => ReactNode \| void` | – | Last-column actions, expandable detail and row click. |
| exportName | `string` | – | File name for CSV export. Omit to hide the button. |
| searchPlaceholder / empty / loading | `string / ReactNode / boolean` | – | Toolbar text, empty state and skeleton rows. |

### Column<T>

Describes one column.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| key / header / accessor | `string / string / (row) => string \| number \| null` | – | accessor feeds sorting, search and export. |
| cell | `(row) => ReactNode` | – | Custom rendering. |
| sortable / filterable / hidden / primary | `boolean` | – | primary is the card title on phones. |
| align / width | `"left" \| "right" / string` | – | Layout. |

## Keyboard interactions

| Keys | Action |
| --- | --- |
| ↑ / ↓ | Move between rows |
| Space | Select the focused row |
| Enter | Expand or open the focused row |
| Tab | Reach toolbar and row controls |

## Accessibility

- A real <table>; sortable headers set aria-sort.
- Every checkbox and filter is labelled.
- Expandable rows set aria-expanded.

## Motion

- Expanded rows animate height; the bulk bar slides up when rows are selected.

## Responsive behavior

- Below 640px rows become cards titled by the primary column.

## Performance

- Sorting and filtering run in memory; for more than ~5,000 rows, page on the server.

## Notes for AI

- accessor must return a primitive; use cell for formatting.
- Keep getRowId stable or selection resets.

## Related

- [Pagination](https://lodeui.com/components/pagination) — Page numbers with ellipses and a gliding current-page indicator.
- [Checkbox](https://lodeui.com/components/checkbox) — A checkbox whose tick draws itself, with an indeterminate state.
- [Dropdown menu](https://lodeui.com/components/dropdown-menu) — Actions, checkboxes and radio options in a springy menu with full keyboard support.
- [Empty state](https://lodeui.com/components/empty-state) — Empty, no-results, error, offline, maintenance and rate-limit states with one API.
