Table
Table renders typed rows as a data table. Columns describe how each cell is rendered, so the same row objects can carry plain values, pills or any other content.
import { Table } from 'jarvis-react-ui';
Columns and rows
Table is generic over the row type. Each TableColumn<T> has a unique key, a header and a
render(row, index) function that returns the cell content. align sets the alignment of header
and cells (right-align numbers), and className is applied to every cell of the column, which is
handy for widths. getRowKey must return a stable, unique key per row.
import { Pill, Table } from 'jarvis-react-ui';
import type { TableColumn } from 'jarvis-react-ui';
interface Subsystem {
id: string;
name: string;
status: 'online' | 'degraded' | 'offline';
load: number;
}
const ROWS: Subsystem[] = [
{ id: 'pwr', name: 'Power core', status: 'online', load: 72 },
{ id: 'com', name: 'Comms array', status: 'degraded', load: 38 },
{ id: 'nav', name: 'Navigation', status: 'online', load: 15 },
{ id: 'def', name: 'Defense grid', status: 'offline', load: 0 },
];
const STATUS_PILL = { online: 'ok', degraded: 'warn', offline: 'err' } as const;
const COLUMNS: TableColumn<Subsystem>[] = [
{ key: 'name', header: 'Subsystem', render: (row) => row.name },
{
key: 'status',
header: 'Status',
align: 'center',
render: (row) => <Pill variant={STATUS_PILL[row.status]}>{row.status}</Pill>,
},
{
key: 'load',
header: 'Load',
align: 'right',
className: 'w-[80px] tabular-nums',
render: (row) => `${row.load}%`,
},
];
export default function Basic() {
return (
<Table
caption="Subsystem status"
columns={COLUMNS}
rows={ROWS}
getRowKey={(row) => row.id}
/>
);
}
Define columns outside the component (or memoize them) so they are not recreated on every render.
TypeScript infers T from rows and checks every render function against it.
Dense with a visible caption
dense tightens the cell padding for compact lists such as logs. The caption is always present
for screen readers; showCaption also shows it as a small heading above the table.
import { Table } from 'jarvis-react-ui';
import type { TableColumn } from 'jarvis-react-ui';
interface LogEntry {
time: string;
source: string;
message: string;
}
const ROWS: LogEntry[] = [
{ time: '12:04:31', source: 'uplink', message: 'Link established' },
{ time: '12:04:32', source: 'auth', message: 'Handshake ok' },
{ time: '12:04:33', source: 'telemetry', message: 'Streaming started' },
];
const COLUMNS: TableColumn<LogEntry>[] = [
{ key: 'time', header: 'Time', className: 'w-[90px] text-text-muted', render: (r) => r.time },
{
key: 'source',
header: 'Source',
className: 'w-[110px] text-accent',
render: (r) => r.source,
},
{ key: 'message', header: 'Message', render: (r) => r.message },
];
export default function DenseWithCaption() {
return (
<Table
caption="Event log"
showCaption
dense
columns={COLUMNS}
rows={ROWS}
getRowKey={(r, index) => `${r.time}-${index}`}
/>
);
}
Empty state
When rows is empty, a single full-width row shows emptyText (default "No data").
import { Table } from 'jarvis-react-ui';
import type { TableColumn } from 'jarvis-react-ui';
interface Alert {
id: string;
level: string;
message: string;
}
const COLUMNS: TableColumn<Alert>[] = [
{ key: 'level', header: 'Level', render: (r) => r.level },
{ key: 'message', header: 'Message', render: (r) => r.message },
];
export default function Empty() {
return (
<Table
caption="Open alerts"
columns={COLUMNS}
rows={[]}
getRowKey={(r) => r.id}
emptyText="No open alerts. All systems nominal."
/>
);
}
The API tables on every component page of this site are rendered with Table.
Accessibility
- Renders a native
<table>with<thead>,<tbody>and<th scope="col">header cells. - Always pass a
caption: it names the table for assistive technology. WithoutshowCaptionit is visually hidden but still read out. - The table sits in a horizontally scrollable container, so wide tables do not break the layout on small screens.
- Rows are not interactive. If a row needs an action, put a button or link into a cell.
API
| Prop | Type | Default | Description |
|---|---|---|---|
columns (required) |
TableColumn<T>[] |
Column definitions in display order. | |
getRowKey (required) |
(row: T, index: number) => string |
Returns a stable unique key for a row. | |
rows (required) |
T[] |
Data rows. | |
caption |
ReactNode |
Accessible caption, rendered visually hidden unless showCaption is set. |
|
className |
string |
Additional class names for the scroll container that wraps the <table>. |
|
dense |
boolean |
false |
Tighter cell padding. |
emptyText |
ReactNode |
No data |
Content shown in a single full-width row when rows is empty. |
showCaption |
boolean |
false |
Shows the caption above the table. |
Type TableColumn<T>
Definition of one Table column; T is the row type.
| Field | Type | Default | Description |
|---|---|---|---|
header (required) |
ReactNode |
Header cell content. | |
key (required) |
string |
Unique key of the column; used as the React key of its cells. | |
render (required) |
(row: T, index: number) => ReactNode |
Renders the cell content for a row; index is the row's position in rows. |
|
align |
TableAlign |
'left' |
Horizontal alignment of header and cells. |
className |
string |
Extra class name for every cell in this column, e.g. one that sets the column width. |
Type TableAlign
Horizontal alignment of a Table column.
type TableAlign = 'left' | 'center' | 'right';