SIGN IN SIGN UP

fix(a11y): keep a tabbable row in every AG-Grid table after scrolling (#14664)

AG-Grid tables use a roving tabindex: exactly one row carries tabindex="0"
so keyboard users can enter the grid. The shared wrapper assigned that tab
stop in patchTabbableRow(), but only scheduled the patch on gridReady,
firstDataRendered and paginationChanged. Row virtualization is scroll-driven
and fires none of those, so once the tab-stop row was recycled out of the DOM
nothing reassigned it — the grid ended with zero tabbable descendants and
could not be entered from the keyboard at all, and did not recover on
scrolling back.

- re-run the accessibility patch on viewportChanged (the rendered row window
  moved) and modelUpdated (sort/filter/data re-renders, which had the same
  hole); the patch is already rAF-debounced so the scroll path stays cheap
- pick the tab stop by the lowest row-index instead of DOM position:
  ensureDomOrder is the wrapper default but consumers can override it via
  gridOptions, and without it DOM order stops tracking visual order
- grid-tabbable-row.spec.ts: scroll a 250-row grid through its full range and
  assert the tab stop survives, plus a keyboard-entry and arrow-navigation
  pass; both fail on release-1.12.0 and pass here
- four unit tests for the recycled-window, out-of-order-DOM and missing
  row-index cases

Clears the IBM aria_child_tabbable violation (WCAG 2.1.1) on
/settings/messages. Row 2.1.1 also needs the canvas keyboard work, so the
compliance form is unchanged.
V
Viktor Avelino committed
eae812a86ee99b163132a045a27f95ac87aa768c
Parent: 8806782
Committed by GitHub <noreply@github.com> on 8/19/2026, 8:41:49 PM