{/* footer: "{n} of {m} selected" + Previous / Next */}
```
### Per-column filters (TanStack Table)
Each header carries a funnel that opens a type-aware filter — “contains” text, a faceted multi-select with live counts, and a date range. Backed by @tanstack/react-table; the kit components read and write column filter state.
```tsx
const columns: ColumnDef[] = [
{
accessorKey: "customer",
header: ({ column }) => (
} />
),
},
{
accessorKey: "status",
filterFn: facetedFilterFn, // scalar cell ∈ selected set
header: ({ column }) => (
} />
),
},
{
accessorKey: "created",
filterFn: dateRangeFilterFn, // { from, to } inclusive, by day
header: ({ column }) => (
} />
),
},
];
const table = useReactTable({
data, columns,
state: { sorting, columnFilters, columnVisibility },
onSortingChange, onColumnFiltersChange, onColumnVisibilityChange,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(), // powers the counts
});
{/* render header/body with flexRender over table.getRowModel() */}
```
## Notes
- Data Table is a pattern, not a single component: it composes Table with Input (filter), Button (sortable headers + pagination), Checkbox (row selection), DropdownMenu (column visibility), and Badge (status).
- The first example keeps state in React for a self-contained demo. The second wires @tanstack/react-table as the headless engine — DataTableColumnHeader, DataTableFacetedFilter, DataTableDateFilter, and DataTableTextFilter all read and write column filter state directly, so the same components work against server-driven data.
- Set each column's filterFn to match its control: facetedFilterFn for multi-select, dateRangeFilterFn for the date range, and TanStack's default includesString for text. Faceted counts come from getFacetedUniqueValues().
- Mark selected rows with data-state="selected" so TableRow gets the muted highlight automatically.