Components
Data table
DataTable is composition, not a new recipe. table() dresses the markup, pagination() sits under the list, and a Select beside the nav owns rows-per-page when a dashboard needs it. TanStack Table (or any headless model) supplies sorting, selection and column state — later, in the app or ui-react.
Anatomy
Showing 1–20 of 412
| Event | Reviews | Score |
|---|---|---|
| Harbor City Marathon | 412 | 4.7 |
| Seabridge Half Marathon | 89 | 3.2 |
What ships in @sportingscouter/ui
| Piece | Export | Owns |
|---|---|---|
| Table visuals | table({ hover, stickyHead, selectable, … }) | Classes only — no column model |
| Pagination visuals | pagination({ scale, layout }) | Classes only — no page math |
| Page window | paginationWindow({ page, pageCount }) | Numbers and ellipsis markers |
| Row slice | paginationSlice({ page, pageSize, total }) | from, to, pageCount — summary copy stays in the app |
| Page size | select() composed beside nav | Not inside pagination() |
| Sort / select / columns | TanStack Table (app / ui-react) | Out of scope for this package |
Empty and error
Use table() empty and error slots — different shapes, same layout. Empty is neutral; error is destructive. Both need a recovery action in stateAction. No illustrations — the system has no imagery. See Empty, loading, error.
Structure
import { table, pagination, paginationWindow, paginationSlice } from '@sportingscouter/ui';
const { from, to, pageCount } = paginationSlice({ page, pageSize, total });
const items = paginationWindow({ page, pageCount });
<div class={tbl.wrap()}>
<table class={tbl.root({ hover: true, stickyHead: true })}>…</table>
</div>
<nav class={pg.root()} aria-label="Pagination">
<p class={pg.summary()} aria-live="polite">{/* app-owned: Showing {from}–{to} of {total} */}</p>
<ul class={pg.list()}>{/* map items from paginationWindow */}</ul>
</nav>
<Select scale="sm" … /> {/* rows per page — beside nav, not inside it */}Rules
- No
dataTable()recipe. Three APIs for one grid is three chances to diverge. Compose what exists. - Table does not grow a footer. Pagination and page-size live outside the
<table>. - Missing score is
—, not0.0. Absence is a state — see Table. - Admin may keep TanStack on its own stack. It adopts these tokens and recipes when ready — this pass does not block it.
See also: Table · Pagination · Select
Sporting Scouter Design System
Every token on this site is generated from
theme.css.