Loading page…
Loading page…
One virtualized table for activity, UTXOs, peers, and explorer data. Rows window against a fixed height via @tanstack/react-virtual; the plate is a ch-frame with mono headers, zebra body rows, and tabular amounts. Prefer Lists when each item is an object, not a column grid.
Comfortable 48px rows for wallet activity; dense 36px rows for the explorer. Headers are click-to-sort — both ship sorted newest first via defaultSort.
12 fixture transactions: send/receive/swap × pending/confirming/confirmed/failed.
import { Table, type TableColumn } from "@coldharbor/webui";
import { transactions, type Transaction } from "@coldharbor/webui/fixtures";
const columns: TableColumn<Transaction>[] = [
{ key: "timestamp", header: "Age", sortable: true },
{ key: "amountDisplay", header: "Amount", align: "right",
cell: (tx) => <span className="font-mono tabular-nums">{tx.amountDisplay}</span> },
];
<Table
data={transactions}
columns={columns}
getRowId={(tx) => tx.id}
defaultSort={{ key: "timestamp", direction: "desc" }}
rowHeight={48}
height={340}
/>--ch-surface--ch-canvas-raised--ch-border--ch-line-faint--ch-fg--ch-fg-muted--ch-primary--ch-shadow-raisePeers specimen — mono endpoints, transport badges, latency sort. Same plate chrome as activity tables.
<Table data={peers} columns={peerColumns} getRowId={(p) => p.id}
defaultSort={{ key: "latencyMs", direction: "asc" }} />--ch-surface--ch-canvas-raised--ch-border--ch-line-faint--ch-fg--ch-fg-muted--ch-primary--ch-shadow-raise500 rows in a 360px viewport. Only the visible window mounts — scroll to confirm the sticky header and zebra striping stay sharp.
<Table data={rows} columns={columns} getRowId={(r) => r.id}
rowHeight={40} height={360} overscan={12} />--ch-surface--ch-canvas-raised--ch-border--ch-line-faint--ch-fg--ch-fg-muted--ch-primary--ch-shadow-raiseselectable adds a leading checkbox column with select-all in the header; selected rows tint with the primary. Two rows ship pre-selected here.
<Table selectable defaultSelectedRowIds={ids} onSelectionChange={setIds} … />--ch-surface--ch-canvas-raised--ch-border--ch-line-faint--ch-fg--ch-fg-muted--ch-primary--ch-shadow-raiseFirst load shows a full-viewport skeleton; paging appends skeleton rows under real data; empty and error render through the emptyState slot.
| No transactions yet — receive your first coins to see them here. | ||||||
| Could not reach the node — check your connection and retry. | ||||||
<Table data={[]} loading … /> // initial skeleton
<Table data={rows} loading skeletonRows={3} … /> // paging skeleton
<Table data={[]} emptyState={<Empty />} … /> // empty
<Table data={[]} emptyState={<FetchError />} … /> // error posture--ch-surface--ch-canvas-raised--ch-border--ch-line-faint--ch-fg--ch-fg-muted--ch-primary--ch-shadow-raiseDrag a header to reorder its column; drag the right edge of a header to resize. Both are opt-in flags.
<Table resizable reorderable minColumnWidth={64} … />--ch-surface--ch-canvas-raised--ch-border--ch-line-faint--ch-fg--ch-fg-muted--ch-primary--ch-shadow-raiseA compact activity table under all three layers.
--ch-surface--ch-canvas-raised--ch-border--ch-line-faint--ch-fg--ch-fg-muted--ch-primary--ch-shadow-raise