List view
The dashboard’s table is not a table. It is a 40px bar of preset pills, active-filter chips and the funnel and ordering menus, then transparent 44px rows with a hover band and no column header. Rows are CSS grid; the page owns the column template. Transactions is the reference implementation.
Order #1042Payment
Succeeded
$42.00Order #1041Payment
Pending
$18.50Order #1038Refund
Succeeded
-$18.50Pro plan · monthlySubscription
Failed
$29.00tsx
import { ListViewBar, LVRow, LVCell, LVEmptyState, LVEmptyIcons } from '@/components/list-view'
<ListViewBar
presets={[{ id: 'all', label: 'All' }, { id: 'failed', label: 'Failed' }]}
presetId={preset} onPresetSelect={setPreset}
chips={chips} // active filters, one chip per dimension
filters={[{ id: 'status', label: 'Status', options, selected }]}
onFilterSelect={(id, opt) => toggle(id, opt)}
display={[{ label: 'Ordering', value: sort, onValueChange: setSort, options: sortOptions }]}
/>
{rows.map((r) => (
<LVRow key={r.id} columns="minmax(0,1.6fr) minmax(0,1fr) auto" onClick={() => open(r)}>
<LVCell bold>{r.title}</LVCell>
<LVCell muted>{r.kind}</LVCell>
<StatusBadge variant="success" icon={CheckSolid}>Succeeded</StatusBadge>
</LVRow>
))}Rules
- No column header. The first cell is bold and identifies the row; the rest are muted.
- The bar is controlled: it renders state the page owns and calls back on every change.
- Loading is five 40px skeleton bars in the row area. Empty is the narrow left-aligned column with a 2×2 glyph cluster describing the shape of the missing data.
- A row is a link when there is a page to go to, a button when it opens a popup, a div otherwise.