Table
Data tables, grids, and tabular display components
Components for displaying and interacting with tabular data.
Prerequisites
- Install the packages
npm install \
@tetherto/mdk-react-devkit \
@tetherto/mdk-react-adapter \
@tetherto/mdk-ui-foundationInstall zod@^4.6.6 first. @tetherto/mdk-react-devkit@0.12.1 declares zod@^4.6.6 as a peer while its
@hookform/resolvers peer pulls a chain that pins zod 3, so the command above aborts with ERESOLVE in a project that
has no zod. Installing zod 4 at the project root resolves it:
npm install zod@^4.6.6- Import styles:
import '@tetherto/mdk-react-devkit/styles.css'
Components
@tetherto/mdk-react-devkit
Data table
import { DataTable } from '@tetherto/mdk-react-devkit'Sortable, paginated, optionally selectable / expandable table built on TanStack React Table. Controlled and uncontrolled modes for each piece of state.
Data contracts
DataTableColumnDef, DataTableRow, DataTableSortingState,
DataTablePaginationState, DataTableRowSelectionState, DataTableExpandedState
are re-exported from @tetherto/mdk-react-devkit.
Example
/**
* Runnable example for DataTable.
*/
import type { DataTableColumnDef } from '@tetherto/mdk-react-devkit'
import { DataTable } from '@tetherto/mdk-react-devkit'
type Miner = {
id: string
status: 'online' | 'warning' | 'offline'
hashrate: number
power_w: number
}
const data: Miner[] = [
{ id: 'miner-01', status: 'online', hashrate: 102.4, power_w: 3200 },
{ id: 'miner-02', status: 'warning', hashrate: 95.1, power_w: 3450 },
{ id: 'miner-03', status: 'offline', hashrate: 0, power_w: 0 },
]
const columns: DataTableColumnDef<Miner, unknown>[] = [
{ accessorKey: 'id', header: 'Miner' },
{ accessorKey: 'status', header: 'Status' },
{ accessorKey: 'hashrate', header: 'Hashrate (TH/s)' },
{ accessorKey: 'power_w', header: 'Power (W)' },
]
export const DataTableExample = () => {
return <DataTable<Miner> data={data} columns={columns} getRowId={(row) => row.id} />
}@tetherto/mdk-react-devkit
Import the public APIs on this page from @tetherto/mdk-react-devkit.
AlertConfirmationModal
Modal that confirms acknowledging or clearing one or more alerts before applying the change
agent-ready
Source
src/domain/components/alerts/current-alerts/alert-confirmation-modal/USAGE.md
src/domain/components/alerts/current-alerts/alert-confirmation-modal/alert-confirmation-modal.tsx
Props
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
isOpen | Required | boolean | - | Controls dialog visibility |
onOk | Required | VoidFunction | - | Called when the user confirms the action |
AlertsTableTitle
Title strip for an alerts table with the section heading and an optional count badge
agent-ready
Source
src/domain/components/alerts/alerts-table-title/USAGE.md
src/domain/components/alerts/alerts-table-title/alerts-table-title.tsx
Props
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
title | Required | React.ReactNode | - | Section heading |
className | Optional | string | - | Additional CSS class |
subtitle | Optional | React.ReactNode | - | Optional subtitle or count badge |
CurrentAlerts
Sortable, searchable data table of currently active alerts derived from a raw devices payload. Plays an audible beep when a critical alert is present (gated by isSoundEnabled + user confirmation modal)
agent-ready
Source
src/domain/components/alerts/current-alerts/USAGE.md
src/domain/components/alerts/current-alerts/current-alerts.tsx
Props
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
filterTags | Required | string[] | - | Search tags (controlled) |
localFilters | Required | AlertLocalFilters | - | Filters controlled outside (typically by URL severity param) |
onFilterTagsChange | Required | (tags: string[]) => void | - | Setter for the tags above |
onLocalFiltersChange | Required | (filters: AlertLocalFilters) => void | - | Setter for the filters above |
className | Optional | string | - | Additional class names |
devices | Optional | Device[] | - | Devices carrying alerts (last.alerts), as a flat list. Unwrapping any backend envelope is the data layer's job, not this component's |
isDemoMode | Optional | boolean | false | Skip sound entirely (e.g. in demo/preview environments), including the one-time "sound notifications" confirmation modal |
isLoading | Optional | boolean | false | Show DataTable loading overlay |
isSoundEnabled | Optional | boolean | false | Whether sound notifications are enabled in user preferences (e.g. theme slice) |
onAlertClick | Optional | ((id?: string | undefined, uuid?: string | undefined) => void) | - | Click handler when the user opens an alert (right arrow icon in the row) |
selectedAlertId | Optional | string | - | Optional id used to focus on a single alert (deep-link from URL) |
typeFiltersForSite | Optional | CascaderOption[] | - | Optional site-specific overrides for the type filter |
DataTable
Generic typed data table built on TanStack React Table. Supports pagination, sorting, expansion, row selection and custom column renderers
agent-ready
Props
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
columns | Required | ColumnDef<I, any>[] | - | The column configuration table. See https://tanstack.com/table/v8/docs/guide/column-defs |
data | Required | I[] | - | The data to be shown in the table. See https://tanstack.com/table/v8/docs/guide/data |
bordered | Optional | boolean | false | Add borders to all cells |
canRowExpand | Optional | ((row: Row<I>) => boolean) | false | Callback to check if a row can be expanded |
contentClassName | Optional | string | - | Classname of the content element |
defaultSorting | Optional | SortingState | [] | Default sorting applied when the table is first mounted (uncontrolled mode). Ignored when sorting is provided |
enableMultiRowSelection | Optional | boolean | true | Enables selection of multiple rows |
enablePagination | Optional | boolean | true | Show pagination |
enableRowExpansion | Optional | boolean | false | Show a columns with a button which can expand the row |
enableRowSelection | Optional | boolean | ((row: Row<I>) => boolean) | false | Show a checkbox column and enables selection |
expandedRows | Optional | ExpandedState | - | Specify the expanded rows If undefined, the expansions are managed internally Object with the key of row ID and a boolean specifying if the row is selected. The default row ID is the index. This can be changed using getRowId prop |
fullWidth | Optional | boolean | true | Is table full width |
getRowId | Optional | ((row: I, index: number, parent?: Row<I> | undefined) => string) | index | Get the row ID for a row. If not specified index is the default row ID |
loading | Optional | boolean | false | Show a loading indicator overlay |
onExpandedRowsChange | Optional | ((expandedRows: ExpandedState) => void) | - | Callback to be called when the rows are expanded or collapsed |
onPaginationChange | Optional | ((pagination: PaginationState) => void) | - | Callback to be called when the pagination params change |
onRowClick | Optional | ((rowData: I) => void) | - | Called when a body row is clicked. When set, rows become interactive (pointer cursor, role="button", keyboard-activatable with Enter/Space). Clicks originating from an interactive control in the row (button, link, input, checkbox, or anything marked data-no-row-click) are ignored, so the selection checkbox and expand toggle keep working independently |
onSelectionsChange | Optional | ((selections: RowSelectionState) => void) | - | Callback to be called when the row are selected / unselected |
onSortingChange | Optional | ((sorting: SortingState) => void) | - | Callback to be called when the sorting changes |
pagination | Optional | PaginationState | undefined | Specify the pagination params. Object of shape { pageIndex: number, pageSize: number }. If undefined then the pagination is managed internally |
renderExpandedContent | Optional | ((row: Row<I>) => React.ReactNode) | - | Render the content of the expanded row. Required when enableRowExpansion is true |
selections | Optional | RowSelectionState | undefined | Specify the selected rows. If undefined, the selections are managed internally Object with the key of row ID and a boolean specifying if the row is selected. The default row ID is the index. This can be changed using getRowId prop |
sorting | Optional | SortingState | undefined | Specify the sorting params. If undefined then the sorting is managed internally |
tableClassName | Optional | string | - | Classname of the table element |
wrapperClassName | Optional | string | - | Classname of the wrapper element |
DeviceExplorer
Device explorer: filter + search toolbar over a sortable, selectable device table. Shows the miner columns by default; pass columns to change them (spread getMinerColumns(...) to extend the default set). Designed to be controlled by URL state in the host app
agent-ready
Props
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
data | Required | Device[] | - | Rows |
filterOptions | Required | DeviceExplorerFilterOption[] | - | Filter category definitions |
getFormattedDate | Required | (date: Date) => string | - | Date formatter from the host's timezone setup; used by the default miner columns |
onFiltersChange | Required | (value: LocalFilters) => void | - | Setter for filters |
onSearchTagsChange | Required | (tags: string[]) => void | - | Setter for search tags |
searchOptions | Required | DeviceExplorerSearchOption[] | - | Searchable column definitions |
searchTags | Required | string[] | - | Active search-tag chips |
className | Optional | string | - | Additional class names |
columns | Optional | ColumnDef<Device>[] | - | Table columns. Defaults to the miner columns (getMinerColumns) |
filters | Optional | LocalFilters | - | Controlled filter values |
onRowClick | Optional | ((device: Device) => void) | - | Called when a row is clicked (e.g. to open the device's detail page) |
onSelectedDevicesChange | Optional | ((selections: RowSelectionState) => void) | - | Setter for row selection |
onSortingChange | Optional | ((sorting: SortingState) => void) | - | - |
selectedDevices | Optional | RowSelectionState | - | Controlled row-selection state |
DeviceExplorerFilterOption
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
label | Required | string | - | Text shown in the filter cascader |
value | Required | string | - | Category key at the top level (e.g. status), or a selectable value under it; selections reach onFiltersChange as [category, value] paths |
children | Optional | DeviceExplorerFilterOption[] | - | Values selectable under this category; omit on leaf options |
DeviceExplorerSearchOption
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
label | Required | string | - | Suggestion text, matched case-insensitively against the typed query and shown on the chip |
value | Required | string | - | Tag added to searchTags when this suggestion is picked (free-text tags are also allowed) |
HistoricalAlerts
Sortable data table of historical alerts within a controlled date range. Renders a header with title + DateRangePicker, then the table
agent-ready
Source
src/domain/components/alerts/historical-alerts/USAGE.md
src/domain/components/alerts/historical-alerts/historical-alerts.tsx
Props
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
dateRange | Required | HistoricalAlertsRange | - | Selected date range for the historical query (controlled) |
filterTags | Required | string[] | - | Shared with CurrentAlerts |
localFilters | Required | AlertLocalFilters | - | Filters and search tags coming from the parent (typically shared with CurrentAlerts) |
onDateRangeChange | Required | (range: HistoricalAlertsRange) => void | - | Setter for the date range |
alerts | Optional | AlertRecord[] | [] | Pre-fetched historical alerts log entries (each with a thing device payload) |
className | Optional | string | - | Additional class names |
isLoading | Optional | boolean | false | Show DataTable loading overlay |
onAlertClick | Optional | ((id?: string | undefined, uuid?: string | undefined) => void) | - | Called when the user opens an alert |
HistoricalAlertsRange
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
end | Required | number | - | Range end, epoch ms; seeds the picker's to date |
start | Required | number | - | Range start, epoch ms; seeds the picker's from date |
TagFilterBar
Horizontal strip of removable tag chips that narrow a list view; clicking a chip removes the filter
agent-ready
Source
src/domain/components/alerts/tag-filter-bar/USAGE.md
src/domain/components/alerts/tag-filter-bar/tag-filter-bar.tsx
Props
| Prop | Status | Type / Options | Default | Description |
|---|---|---|---|---|
filterTags | Required | string[] | - | Active tag filter values |
localFilters | Required | AlertLocalFilters | - | Current local filter state |
onLocalFiltersChange | Required | (filters: AlertLocalFilters) => void | - | Called when any local filter changes |
onSearchTagsChange | Required | (tags: string[]) => void | - | Called when tag filter changes |
className | Optional | string | - | Additional CSS class |
placeholder | Optional | string | - | Search input placeholder |
typeFiltersForSite | Optional | CascaderOption[] | - | Site-specific overrides for the "type" filter children. If provided, the "Type" filter group will use these instead of the defaults |