Data table (admin-grade)
Admin-grade tabular component — sortable columns, multi-select with bulk actions, sticky header, pagination or virtualization, saved column views, expandable rows, inline edit. Modeled after Polaris IndexTable, PatternFly Table+Toolbar, Material 3 DataTable.
Component — Data table
*tatus* v0.1.0 — Draft. Behavioral contract; rendering choice (HTML table vs virtualized list) is implementation detail.
R1 — Column sort
- Single-column sort: click header → ascending; click again → descending; click again → unsorted.
- Multi-column sort: Shift+click adds secondary sort; numeric badge shows priority.
- Sortable columns marked with directional arrow icon; unsortable columns omit the icon.
R2 — Row selection
- Single-select mode: single column of radio buttons.
- Multi-select mode: single column of checkboxes; header checkbox toggles all visible.
- Range select: Shift+click checkbox extends selection from last clicked.
- Selection state announced via live region: "{N} of {total} rows selected".
R3 — Bulk-action bar
- When ≥ 1 row selected, the column
header row morphs into a bulkaction bar:- Left:
{N} selected+ Clear button. - Right: action buttons (Delete, Move, Export, …).
- Left:
- Animated slide
in (200ms; prefersreduced-motion: instant swap). - Bar is sticky alongside the header during scroll.
R4 — Sticky header
- Header row stays visible during vertical scroll within the table viewport.
- On nested
page scroll past the table top, header may pin to viewport top (pagelevel decision; not all surfaces want this).
R5 — Pagination vs virtualization (decision tree)
| Row count | Use |
|---|---|
| < 50 | No pagination; render all |
| 50–500 | Pagination (2550100 per page) |
| 500–5,000 | Cursor pagination + load-more button |
| > 5,000 | Virtualization (windowed render); show count + filter to drive down |
R6 — Saved views
- User saves named view: name + columns + sort + (filters from
specs/components/index-filters.kmd). - Views persisted per
user + pertable-identity. - View dropdown in toolbar; default view always present.
R7 — Expandable rows
- Optional per-table: row caret toggles inline expansion.
- Expanded content lives inside the row; not modal.
- Only one row expanded at a time (accordion) OR multiple (parallel) — table-level config.
R8 — Inline edit
- Optional per-column: cell focus → field edit mode.
- Enter commits; Esc reverts; Tab commits + moves to next editable cell.
- Live region announces commit success ("Saved: {field} = {value}") or failure.
R9 — Keyboard nav
| Key | Action |
|---|---|
| Tab | Move through interactive cells (links, buttons, selects) |
| Shift+Tab | Reverse |
| ↑/↓ | Navigate row by row |
| ←/→ | Navigate cell by cell within a row |
| Space (on row checkbox cell) | Toggle selection |
| Enter (on row) | Activate primary row action (open detail) |
R10 — Screen-reader semantics
<table>element with<caption>(table name) oraria-label.<th scope="col">for column headers;aria-sortreflects sort state.<tr>for row; selected rows havearia-selected="true".- Bulk action bar replaces header semantically (announces via live region).
R11 — OUIA hooks
Per specs/testing/ouia-test-hooks.kmd:
data-ouia-component-type="DataTable"data-ouia-component-id="<table-slug>"data-ouia-safe="true"only when data loaded + no pending edits.
R12 — Empty / loading
- Empty: render per
specs/patterns/empty-state.kmdinside the table container (no row stripes). - Loading: render per
specs/components/skeleton.kmd(5 skeleton rows mirroring final column layout).
Não-escopo
- Server
side data fetching (transportagnostic). - Specific virtualization library (TanStack Virtual, react-window, etc.).
- Charting overlays (separate spec if needed).
- Pro-layer wrapping (search bar + saved views + density toggle +
column visibility menu + export bundled as a single component) — evaluated in design
RFC008 and *atified Option C (recipe pattern only)*on 20260523. Consumers compose the toolbar themselves followingspecs/patterns/admin-data-table.kmd; KDS does NOT ship a bundled Pro component.