# Data table

> Typed table with sorting, row selection and loading, empty, no-results and error states; rows glide to their new order on sort and a bulk-action bar springs up as you select.

- Collection: Components
- Tier: pro
- Docs: https://geturui.com/docs/data-table
- Install: `npx shadcn@latest add @geturui-pro/data-table`
- Dependencies: motion, lucide-react

## Usage

```tsx
import { AvatarCell, BadgeCell, DataTable, type DataTableColumn } from "@/components/ui/data-table";

type Member = { id: string; name: string; email: string; status: "Active" | "Invited"; installs: number };

const columns: DataTableColumn<Member>[] = [
  { id: "name", header: "Member", rowHeader: true, sortable: true, accessor: (m) => m.name, cell: (m) => <AvatarCell name={m.name} description={m.email} /> },
  { id: "status", header: "Status", cell: (m) => <BadgeCell tone={m.status === "Active" ? "success" : "info"}>{m.status}</BadgeCell> },
  { id: "installs", header: "Installs", sortable: true, align: "end", accessor: (m) => m.installs, hideBelow: "sm" },
];

export function Members({ members }: { members: Member[] }) {
  return (
    <DataTable
      caption="Workspace members"
      title="Team members"
      data={members}
      columns={columns}
      getRowId={(m) => m.id}
      getRowLabel={(m) => m.name}
      selectable
      bulkActions={(ids, clear) => <button onClick={clear}>Remove {ids.length}</button>}
    />
  );
}
```

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| data | `T[]` | — | Rows to show, already filtered. |
| columns | `DataTableColumn<T>[]` | — | id, header, accessor, cell, sortable, sortFn, align, width, hideBelow (sm–2xl), rowHeader, className. |
| getRowId | `(row: T) => string` | — | Stable id per row; keys the reorder animation and selection. |
| caption | `string` | — | Screen reader caption. The current sort is appended automatically. |
| getRowLabel | `(row: T) => string` | — | Name used in each row checkbox label. |
| title / description / count / toolbar | `ReactNode` | — | Optional card header with a count badge and a right-hand slot for search, filters or buttons. |
| sort / defaultSort / onSortChange | `{ columnId, direction } | null` | — | Sort state. Headers cycle ascending, descending, off. |
| selectable | `boolean` | false | Adds a checkbox column; the header box turns indeterminate on partial selection. |
| selected / defaultSelected / onSelectedChange | `string[]` | — | Selected row ids. |
| bulkActions | `(ids, clear) => ReactNode` | — | Contents of the floating bar shown while rows are selected. |
| rowActions | `(row: T) => ReactNode` | — | Trailing cell per row; bring your own buttons or menu. |
| density | `"compact" | "comfortable"` | "comfortable" | Row height and cell padding. |
| striped | `boolean` | false | Alternate row fills. |
| stickyHeader / maxHeight | `boolean / number | string` | — | Pin the header inside a scrolling body. |
| status | `"ready" | "loading" | "error"` | "ready" | Loading shows shimmer skeleton rows; error shows a retry state. |
| filtered | `boolean` | — | An empty result shows no-results (with onClearFilters) instead of the empty state. |
| emptyState / noResultsState / errorState | `ReactNode` | — | Replace the built-in state blocks. |
| onRetry / onClearFilters | `() => void` | — | Adds Try again and Clear filters buttons to the built-in states. |
| footer | `ReactNode` | — | Slot under the table for pagination or totals. |
| AvatarCell / BadgeCell / ProgressCell / TrendCell | `components` | — | Cell helpers: initials avatar with two lines, status badge with dot, inline progress bar, signed trend with arrow. |

## Accessibility

- A real <table> with a screen-reader caption; the name column renders th scope="row".
- Sortable headers are buttons and the sorted column carries aria-sort; the caption states the current sort.
- Row checkboxes are named "Select {row}"; the select-all box reports mixed when partially checked.
- The scroll region is focusable and labelled so keyboard users can scroll wide tables.
- Trend and status cells carry words, not colour alone. Row reorder, bar and shimmer animations are dropped under reduced motion.

## Source

Pro item — send `Authorization: Bearer <registry token>` to include the source.
