Segment table — accessibility

Keyboard

  • The table is a real <table> with thead, tbody and tfoot, 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 adds tabIndex=0 and handles Enter and Space. That keeps the table semantics intact — a role="button" on a <tr> would destroy them.
  • The checkbox is a real <input type="checkbox">; the visible .ck box 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 sets outline: none only 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 --selected as 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 EmptyState fallback (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