Segment table
canonListing table: sortable header, frozen checkbox and identity columns, lazy loading by 50 and an optional summary row in its own tfoot.
Engine lives in the app (components/segment/SegmentScreen.tsx — SegmentTable); the lite variant strips checkbox, column menu, summary and frozen identity. Row height is --row-h (37px) — the 44/52 densities belong to Item list, not here. The registry previously listed .sgb-summary, which does not exist: the summary row is the table tfoot and .sgb-sum is the per-column control.
Used in 23 files · 22 areas · 23× — pages/AccountingInvoicesPage, pages/AccountingOpenItemsPage, pages/AccountingReceivedInvoicesPage, pages/AiZamestnanciPage, pages/DokumentyPage, pages/FirmyPage …
apps/web <SegmentTable> <SegmentScreen>.table-wrap .sgb-table .sgb-th-col .sgb-th-sortable +3SourceStoryLegacy card list-view.htmlKeyboard
- The table is a real
<table>withthead,tbodyandtfoot, so screen readers announce rows, columns and headers. - Rows are not buttons: a row that opens something keeps its
<tr>and the screen opts into keyboard operation (rowKeyboard), which addstabIndex=0and handles Enter and Space. That keeps the table semantics intact — arole="button"on a<tr>would destroy them. - The checkbox is a real
<input type="checkbox">; the visible.ckbox is its sibling, so Space toggles the selection from the keyboard. - Sorting is triggered from the header control; the per-column menu opens with Enter.
ARIA
- Header cells are
<th>, so the column name is announced with every cell. - The select-all checkbox carries its own label; row checkboxes are labelled by the record (
Vybrat Brno Tech a.s.). - The summary row is a
<tfoot>of the same table, so its cells inherit the column headers. - Nothing announces that more rows were loaded as the user scrolled.
Focus
- Rows and cells rely on the foundation ring from
ds.css; the sheet setsoutline: noneonly on text inputs inside the table chrome (search fields), never on rows or cells. - The checkbox has a custom ring: because the real input is visually hidden, the ring is drawn on the sibling box (
input:focus-visible + .ck). - The frozen identity and checkbox columns stay in place while the table scrolls sideways, so a focused row never slides out of context.
Contrast
Computed from packages/ui/src/tokens/tokens.css:
- Cell text in ink on the table surface — above AA in both themes.
- Muted column labels and secondary cells sit at
--fg-muted= 2.85:1 light, 3.63:1 dark — below AA for text. - Selected row uses
--selectedas a fill; hover uses--hover-surface— both are non-text tints and are not the only carrier of state (the checkbox is). - The scroll shadow behind the frozen columns is decorative.
Known limits
- There is no empty state. A listing with no rows shows the header and nothing under it; the engine has no
EmptyStatefallback (a gap, not just a missing story). - Lazy loading is silent for assistive technology.
- Muted cells and column labels sit below AA in light theme.
- The column menu appears on hover, so on touch it is reachable only through the header control itself.
Source: docs/table/segment-table.a11y.md · GitLab