Blocks
Table Manager
A composable toolbar + data table block with server-side filtering, client-side sorting, column visibility toggling, multiselect filters, date range picking, pagination, and export.
page.tsx
Rows
Service Applet | Origin | |||||
|---|---|---|---|---|---|---|
| Jerome Bell | ![]() ![]() | PASSED | MeldCx HQ | Jun 28, 2024, 5:00 PM | AI | |
| Cameron Williamson | ![]() ![]() | FAILED | MeldCx PH | Jun 27, 2024, 5:00 PM | AI | |
| Brooklyn Simmons | ![]() | PASSED | MeldCx CA | Jun 26, 2024, 5:00 PM | AI | |
| Savannah Nguyen | ![]() ![]() ![]() | PASSED | MeldCx GE | Jun 25, 2024, 5:00 PM | AI | |
| Jerome Bell | ![]() ![]() | PASSED | MeldCx US | Jun 24, 2024, 5:00 PM | AI |
0 of 5 rows selected.
Rows
Import
tsx
import {
TableManager,
TableManagerToolbar,
TableManagerSearch,
TableManagerToolbarActions,
TableManagerMultiFilter,
TableManagerDateRange,
TableManagerRowsPerPage,
TableManagerPagination,
TableManagerColumnToggle,
TableManagerExport,
TableManagerContent,
TableManagerFooter,
} from "@/components/blocks/TableManager"API Reference
TableManager
| Prop | Type | Default | Description |
|---|---|---|---|
| columns | TableManagerColumnDef<T>[] | required | Column definitions. Drive table headers, cell renderers, sort, and filter. |
| data | T[] | required | Server-filtered rows for the current page. Must have id: string | number. |
| totalCount | number | required | Total number of records across all pages (for pagination math). |
| loading | boolean | false | Shows a loading overlay on the table content while data is fetching. |
| defaultRowsPerPage | number | 20 | Initial rows-per-page value. |
| defaultVisibleColumns | string[] | all | Column IDs to show on initial render. Defaults to all columns with defaultVisible !== false. |
| onSearchChange | (term: string) => void | — | Fired when the search input changes (debounced 300ms). |
| onFilterChange | (filters: Record<string, string[]>) => void | — | Fired when any multiselect filter changes. |
| onDateRangeChange | (range: { from?: Date; to?: Date }) => void | — | Fired when the date range changes. |
| onPageChange | (page: number) => void | — | Fired when the page changes (0-indexed). |
| onRowsPerPageChange | (rowsPerPage: number) => void | — | Fired when rows per page changes. |
| onSelectionChange | (rows: T[]) => void | — | Fired when row selection changes. |
TableManagerColumnDef
tsx
type TableManagerColumnDef<T> = {
id: string // Unique column identifier
header: string // Column header label
type?: "date" | "text" | "other" // Drives default sort order
accessorKey?: keyof T // Key for reading cell values
cell?: (row: T) => React.ReactNode // Custom cell renderer
enableSorting?: boolean // Click label to sort (default: false)
enableFiltering?: boolean // Show filter icon on header (default: false)
filterPopover?: () => React.ReactNode // Content for the column's filter popover
defaultVisible?: boolean // Initially visible (default: true)
}TableManagerFilterOption
tsx
type TableManagerFilterOption = {
value: string
label: string
icon?: React.ReactNode
}TableManagerExportOption
tsx
type TableManagerExportOption = {
label: string // "CSV", "PDF", "Excel"
value: string
icon?: React.ReactNode
}Data model
TableManager uses a hybrid data model: filtering is server-side, sorting is client-side.
- Filtering — The block fires callbacks (
onSearchChange,onFilterChange,onDateRangeChange). The consumer fetches filtered data and passes it back viadata. - Sorting — The block sorts the
dataarray client-side. Default sort: firsttype="date"column descending; if none, firsttype="text"column ascending. - Pagination — Server-side. The consumer passes
totalCountfor pagination math and one page of data at a time. - Row identity — All data objects must have
id: string | number.
Column header interactions
Each column header supports two independent click targets:
- Label click — sorts the column client-side (if
enableSorting: true). Cycles desc → asc → default. - Filter icon click — opens a popover anchored to the header (if
enableFiltering: trueandfilterPopoveris provided). The consumer supplies the popover body.
Column visibility is controlled by the Columns icon button in the toolbar — not by column header clicks.
Extending the toolbar
TableManagerToolbarActions is an open slot — place any additional controls inside it. Built-in controls (TableManagerMultiFilter, TableManagerDateRange, etc.) can be omitted if not needed.
tsx
<TableManagerToolbarActions>
{/* Built-in controls */}
<TableManagerMultiFilter name="applet" label="Applet" options={options} />
<TableManagerDateRange />
<TableManagerRowsPerPage />
<TableManagerPagination />
<TableManagerColumnToggle />
<TableManagerExport options={exportOptions} onExport={handleExport} />
{/* Your custom controls */}
<AppButton variant="outline" size="sm">Custom Action</AppButton>
</TableManagerToolbarActions>

