Skip to content

DataTable

Columns are data, not markup: each says how to render a cell and whether it sorts. Sorting and selection are controlled, and large lists can be virtualised.

import { useState } from 'react'; import { Chip, DataTable, EmptyState, sortRows } from '@andrewbehma/glass-ui';

Playground

DataTable.tsx
import { useState } from 'react';
import { Chip, DataTable, EmptyState, sortRows } from '@andrewbehma/glass-ui';
function Example() {
const rows = [
{ id: 'inv-1042', customer: 'Northwind', amount: 1280, status: 'Paid' },
{ id: 'inv-1043', customer: 'Lumen Studio', amount: 640, status: 'Due' },
{ id: 'inv-1044', customer: 'Halcyon Labs', amount: 3920, status: 'Paid' },
{ id: 'inv-1045', customer: 'Brightwater', amount: 215, status: 'Overdue' },
{ id: 'inv-1046', customer: 'Orbital Goods', amount: 1730, status: 'Due' },
];
const columns = [
{ id: 'id', header: 'Invoice', cell: (r) => r.id, sortable: true },
{ id: 'customer', header: 'Customer', cell: (r) => r.customer, sortable: true },
{
id: 'status',
header: 'Status',
cell: (r) => (
<Chip size="sm" tone={r.status === 'Paid' ? 'ok' : r.status === 'Due' ? 'warn' : 'danger'}>
{r.status}
</Chip>
),
},
{ id: 'amount', header: 'Amount', cell: (r) => `$${r.amount.toLocaleString('en-US')}`, sortable: true, align: 'end' },
];
const [sort, setSort] = useState({ columnId: 'amount', direction: 'desc' });
const [selection, setSelection] = useState(new Set(['inv-1044']));
const sorted = sortRows(rows, columns, sort, (r, id) => r[id]);
return (
<div className="w-full max-w-2xl">
<DataTable
rows={sorted}
getRowId={(r) => r.id}
columns={columns}
sort={sort}
onSortChange={setSort}
selection={selection}
onSelectionChange={setSelection}
emptyState={<EmptyState title="No invoices" description="Invoices you send appear here." />}
/>
</div>
);
}

States

Each tile is the live component. Open one in the playground to keep tweaking it.

  • Selectable
  • Loading
  • Empty