TreeDataTable
A DataTable whose rows form a tree. Parent and leaf nodes share the columns; the tree column indents each row by depth and gives parents a chevron. Tree order is the row order, so sorting and grouping are not offered.
Import
Section titled “Import”import { TreeDataTable } from "@flanksource/clicky-ui/data";The props table documents the component-specific surface. Standard DOM attributes inherited from React, such as className, event handlers, and accessibility attributes, may also be accepted when the component’s prop type extends a native element.
| Prop | Type | Default | Description |
|---|---|---|---|
autoFilter |
boolean |
— | Generate filters from filterable columns. |
boundedFilters |
Record<string, FilterBarDurationValue> |
— | Controlled bounded filter selections, e.g. when persisted in the route URL. |
cellFilters |
Record<string, Record<string, CellFilterMode>> |
— | Current modes for native server-backed cell filters. |
className |
string |
— | Classes applied to the table shell. |
columnResizeStorageKey |
string |
— | Storage key for persisted column widths. |
columns* |
DataTableColumn<T>[] |
— | — |
columnVisibilityStorageKey |
string |
— | Storage key for persisted column visibility. |
defaultDensity |
enum |
— | Initial row density for uncontrolled usage. |
defaultExpanded |
(…) => … |
— | Whether a node without an override starts open. Defaults to false. |
defaultHiddenColumns |
string[] |
— | Column keys that start hidden but stay listed in the column menu, unlike Clicky's `hiddenColumns`, which removes a column outright. Persisted visibility is stored as overrides of these defaults. |
density |
enum |
— | Controlled row density. |
densityStorageKey |
string |
— | Storage key for persisted density. |
detailDialogSize |
enum |
— | Modal size for the detail dialog. Defaults to "lg". |
detailDialogTitle |
(…) => … |
— | Title for the detail dialog (detailStyle="dialog"). Pass a function to derive a per-row title, e.g. `(row) => \`Session ${row.sessionId}\``. |
detailStyle |
enum |
— | How `renderExpandedRow` detail is surfaced when a row is clicked. - "row" (default): expands an inline detail row beneath the clicked row. Multiple rows can be open at once. - "dialog": opens the detail content in a centered modal; one row at a time. The same `renderExpandedRow` (and its context) drives both styles. |
emptyMessage |
string |
— | Message used when there are no rows after filtering. |
error |
ReactNode |
— | Error content rendered as an accessible full-width row in the table body. |
expanded |
TreeExpansion |
— | Controlled expansion overrides. Requires `onExpandedChange`. |
expandedRowIds |
string[] |
— | Controlled ids of rows with inline detail open. |
externalFilters |
FilterBarFilter[] |
— | Extra filter pills supplied by the caller (e.g., operation query parameters surfaced via parametersToFormConfig) that should appear in the FilterBar alongside the column-derived filters. Rendered before the column filters so the caller's natural ordering wins. |
externalSearch |
FilterBarSearchProps |
— | Caller-owned search input rendered in the FilterBar's search slot. Unlike `globalFilter`, this does NOT filter rows client-side — it is a controlled input the caller wires to a server-side query (e.g., an operation's `q` parameter). Takes precedence over the built-in global filter input. |
externalTimeRange |
FilterBarRangeProps |
— | Caller-owned time-range control rendered in the FilterBar. Like `externalSearch`/`externalFilters`, it does NOT filter rows client-side — the caller wires it to a server-side query (e.g. an operation's `time-from`/`time-to` parameters). Takes precedence over any column-derived time range. |
filterBarProps |
Omit<FilterBarProps, "search" | "filters"> |
— | Extra props forwarded to the internal FilterBar. |
footer |
(…) => … |
— | Replaces the default "N of M rows" strip below the table. When `pagination` is also set, this renders directly above the pager instead. |
fullscreenButtonLabel |
string |
— | `aria-label` and `title` for the fullscreen toggle button. Defaults to "Open table full screen". LogsTable overrides to "Open logs full screen". |
fullscreenTitle |
ReactNode |
— | Title shown in the fullscreen modal. |
getAriaLabel* |
(…) => string |
— | Names a parent node in its expand/collapse button. |
getChildren* |
(…) => T[] | undefined |
— | — |
getKey* |
(…) => string |
— | — |
getRowClassName |
(…) => string |
— | Extra classes for a row's `<tr>`, applied last so tailwind-merge lets the caller override the built-in hover / selected backgrounds. |
getRowHref |
(…) => string |
— | Optional href for row link affordances. |
globalFilter |
string |
— | Controlled global search value. |
globalFilterPlaceholder |
string |
— | Placeholder for the global search input. |
hideableColumns |
boolean |
— | Enables column visibility controls. |
infinite |
DataTableInfinite |
— | Server-driven infinite scroll. The caller owns the accumulated rows; this only says when to ask for more. Combines with `pagination` — see DataTableInfinite. |
isRowClickable |
(…) => boolean |
— | Predicate controlling whether a row is clickable. |
loading |
boolean |
— | Shows skeleton/loading rows instead of data rows. |
loadingMessage |
ReactNode |
— | Message shown while `loading` is true. |
loadingRowCount |
number |
— | Number of skeleton rows to render while loading. |
manualFilter |
boolean |
— | When true, filters update state but do NOT narrow `data`. The mirror of `manualSort`: the source owns filtering and DataTable only renders the controls. Suppresses the client-side filter pass, the built-in search's row narrowing, and the column-derived time range. |
manualSort |
boolean |
— | When true, header sorting updates state but does not reorder `data`. |
menuActions |
DataTableMenuAction[] |
— | Extra actions rendered in the table preferences menu. |
onBoundedFiltersChange |
(…) => void |
— | — |
onCellFilterChange |
(…) => void |
— | Called when a cell's include/exclude hover action changes. |
onDensityChange |
(…) => void |
— | Called when density changes. |
onExpandedChange |
(…) => void |
— | — |
onExpandedRowIdsChange |
(…) => void |
— | Called with the next open row ids when an inline detail row is toggled. |
onGlobalFilterChange |
(…) => void |
— | Called when the global search changes. |
onRowClick |
(…) => void |
— | Called when a clickable row is selected. |
onThemeChange |
(…) => void |
— | — |
pagination |
DataTablePagination |
— | Server-side pagination footer. When provided, a small page-size / prev / next strip is rendered below the table; the DataTable does NOT slice `data` itself, callers are expected to refetch when `onPageChange` or `onPageSizeChange` fires. |
persistColumnVisibility |
boolean |
— | Persists column visibility to localStorage. |
persistColumnWidths |
boolean |
— | Persists column widths to localStorage. |
persistDensity |
boolean |
— | Persists density to localStorage. |
renderCard |
(…) => ReactNode |
— | Render each result as a full-width card while retaining filters and paging. |
renderExpandedRow |
(…) => ReactNode |
— | Detail content rendered for expanded rows or dialog details. |
resizableColumns |
boolean |
— | Enables column drag resize handles. |
roots* |
T[] |
— | — |
rowSelection |
DataTableRowSelection<T> |
— | Controlled checkbox selection for entity/bulk-action tables. |
scrollContainerClassName |
string |
— | Classes for the scrollable table region. Defaults to `min-h-0 flex-1` (fills a bounded flex parent). Pass e.g. `max-h-[26rem]` to cap height. |
scrollContainerRef |
RefObject<HTMLDivElement | null> |
— | Handle on the scrollable table region, for a caller that has to drive the scroll position itself — pinning a live tail to the bottom, say. The table never writes through it; it is exposed because a follow mode has to be able to keep the newest row in view, and nothing outside the component can reach that element otherwise. |
selectionActions |
(…) => … |
— | Bulk actions, rendered in the toolbar beside the table menu while `rowSelection` holds a non-empty selection — next to what the selection covers, and above the rows it acts on. Ignored without `rowSelection`. A list is the form to reach for: the table renders the buttons, the count, the Clear, the overflow menu, the pending state while an async action is in flight, and the prompt in front of a destructive one — the same way it renders `menuActions`. The render-prop form stays for the cluster that is genuinely bespoke (a running total, a bar with its own layout) and hands back the plumbing only. |
selectionBar |
enum |
— | Where the bulk cluster goes while rows are selected. "takeover" — it replaces the filter row in place: the filters stay mounted behind it and come back when the selection clears, so nothing below the bar moves. Only honoured for the descriptor (array) form of `selectionActions`; a render-prop cluster is the caller's own markup and the table cannot claim the row on its behalf. "toolbar" (the default) — the cluster rides in the filter bar's trailing slot beside the table menu, sharing the row with the filters. |
showDensityControl |
boolean |
— | Shows density controls in the column menu. |
showFullscreenControl |
boolean |
— | Render a fullscreen-toggle button in the FilterBar's trailing slot (just before the column-menu trigger). When clicked, the table re-renders inside a full-viewport `<Modal>`. Defaults to `false`. |
showGlobalFilter |
boolean |
— | Show the built-in global search input. Defaults to `autoFilter` — the box narrows rows client-side, so it only mounts by default where DataTable already owns filtering. Set it explicitly to search a table that generates no column filters; combine with `manualFilter` plus `globalFilter` / `onGlobalFilterChange` (or use `externalSearch`) to drive a source query. |
showHeaderFilters |
boolean |
— | Shows per-column filter buttons in table headers. |
showThemeControl |
boolean |
— | Shows theme controls in the column menu. |
theme |
enum |
— | Initial / controlled theme value for the column-menu Theme section. When `onThemeChange` is omitted, the DataTable manages this internally (seeded from `theme`) and applies `data-theme` to its root so the table reflects the choice without requiring an enclosing `<ThemeProvider>`. |
treeColumn* |
string |
— | Key of the column that carries the indent and the expand/collapse chevron. |
virtualize |
boolean | { overscan?: number; estimateRowHeight?: number; } |
— | Row virtualization. Only the rows near the viewport stay in the DOM; the rest are represented by spacer rows above and below the window. Row heights are measured, so variable-height cells need no height hint. Reach for it above roughly 200 rows. Off by default because it changes what find-in-page, print and a screen reader see — that is the caller's call, not something to infer from `data.length`. Composes with `infinite` (virtualizing accumulated server pages is the point of both) and with `pagination`. Column widths are pinned on first measure once active, so they do not resize as you scroll. |