Table
A data table with sortable columns, single/multiple row selection, and built-in pagination, loading, and empty states — reuses Checkbox, Pagination, Skeleton, and Empty State under the hood.
| Ava Patel | Frontend Engineer | Active |
| Marcus Lee | Backend Engineer | Active |
| Sofia Ruiz | Product Designer | Invited |
| Noah Kim | DevOps Engineer | Active |
| Elena Novak | QA Engineer | Suspended |
API
All inputs and configuration options for zyra-table.
| Prop | Type | Default | Description |
|---|---|---|---|
columns | TableColumn<T>[] | required | { key, label, sortable?, align?, width?, format? } per column |
rows | T[] | required | The data to display, one object per row |
rowKey | (row: T, index: number) => string | number | (row, index) => index | Derives a stable identity per row, used for selection and tracking |
selectionMode | 'none' | 'single' | 'multiple' | 'none' | Adds a radio or checkbox selection column |
selected | (string | number)[] | [] | Two-way bound via [(selected)] — the row keys currently selected |
sort | { key: string; direction: 'asc' | 'desc' } | null | null | Two-way bound via [(sort)] — the active sort column and direction |
manualSort | boolean | false | Disables internal sorting so a server can sort instead — sort still updates on header click |
pageSize | number | null | null | When set, slices rows into pages and renders a Pagination footer |
page | number | 1 | Two-way bound via [(page)] — the current page when pageSize is set |
loading | boolean | false | Shows skeleton rows instead of data |
size | 'sm' | 'md' | 'lg' | 'md' | Row height and font scale |
rowClick (output) | T | - | Emits the clicked row (not emitted when a selection control is clicked) |
Tokens
CSS custom properties zyra-table reads at runtime — override any of these in your own stylesheet after @use 'zyra-ng-ui'; to restyle it without touching the component itself.
| Token | Default points to | Description |
|---|---|---|
Border--zyra-color-border-color | var(--zyra-color-border) | Outer border, and the divider under each header/row. |
Header background--zyra-color-surface | var(--zyra-color-card-bg) | Fill color of the header row. |
Header text--zyra-color-foreground-subtle | var(--zyra-color-text-dim) | Label color of column headers, and the sort icon. |
Cell text--zyra-color-foreground | var(--zyra-color-text) | Text color of a data cell. |
Row hover / selected--zyra-color-table-row-hover-bg | var(--zyra-color-surface-inset) | Background of a hovered or selected row. |
Focus ring--zyra-color-primary | var(--zyra-color-accent) | Outline color when a header or row is keyboard-focused, and the radio accent-color. |
Accessibility
Built to meet WCAG 2.0 AA. These notes cover the key ARIA, keyboard, and interaction behaviours.
- Renders a native <table>/<thead>/<tbody> — no ARIA table roles needed
- Sortable headers are real <button> elements with aria-sort reflected on the parent <th>
- Two independent roving-tabindex zones — sortable headers and body rows — each with a single tab stop
- Left/Right move between sortable headers; Up/Down move between rows; Down from a header enters the first row, Up from the first row returns to the header
- Home/End jump to the first/last row; Enter/Space on a focused row fires rowClick and toggles selection
- Select-all and per-row checkboxes reuse the accessible Checkbox component
- Single-selection mode uses native radio inputs grouped per table instance