Skip to content

Overhaul grid a11y, navigation and rendering - #79

Merged
rkaraivanov merged 1 commit into
masterfrom
rkaraivanov/feat-add-a11y
Aug 25, 2026
Merged

Overhaul grid a11y, navigation and rendering#79
rkaraivanov merged 1 commit into
masterfrom
rkaraivanov/feat-add-a11y

Conversation

@rkaraivanov

Copy link
Copy Markdown
Member

Screen readers were silent over the grid body: ARIA state lived on scattered attributes and DOM focus never reached the cells. Holding an arrow key re-rendered every visible row per keystroke.

Accessibility

  • Implement the full ARIA grid pattern through ElementInternals: roles, row/column counts and indices, aria-sort, aria-selected. The filter row is modeled as a second header row.
  • Use roving focus. Navigation and click activation place real DOM focus on the active cell so assistive technology announces it; aria-activedescendant cannot cross shadow boundaries. The virtualizer reclaims focus when scrolling removes the focused cell.

Performance

  • Keep the row renderer identity stable across activation. The virtualizer re-renders all rows when renderItem changes, so activation now updates only the two affected rows.
  • Derive column track sizes only when the configuration changes and notify context consumers at mutation points, not on every host update.

API and structure

  • navigateTo(row, options) replaces positional arguments. Activation without a column keeps the current one instead of clearing it.
  • Rename internal tags to the igc-grid-lite-* prefix.
  • Defer filter row and editor element definitions until a filterable column renders.
  • Route all render-root queries through the DOM controller so other controllers no longer reach into the grid DOM directly.
  • Skip filter expressions whose conditions no column resolved.

Screen readers were silent over the grid body: ARIA state lived on
scattered attributes and DOM focus never reached the cells. Holding
an arrow key re-rendered every visible row per keystroke.

Accessibility
- Implement the full ARIA grid pattern through ElementInternals:
  roles, row/column counts and indices, aria-sort, aria-selected.
  The filter row is modeled as a second header row.
- Use roving focus. Navigation and click activation place real DOM
  focus on the active cell so assistive technology announces it;
  aria-activedescendant cannot cross shadow boundaries. The
  virtualizer reclaims focus when scrolling removes the focused
  cell.

Performance
- Keep the row renderer identity stable across activation. The
  virtualizer re-renders all rows when renderItem changes, so
  activation now updates only the two affected rows.
- Derive column track sizes only when the configuration changes and
  notify context consumers at mutation points, not on every host
  update.

API and structure
- navigateTo(row, options) replaces positional arguments. Activation
  without a column keeps the current one instead of clearing it.
- Rename internal tags to the igc-grid-lite-* prefix.
- Defer filter row and editor element definitions until a filterable
  column renders.
- Route all render-root queries through the DOM controller so other
  controllers no longer reach into the grid DOM directly.
- Skip filter expressions whose conditions no column resolved.
@rkaraivanov rkaraivanov added 🪛 enhancement New feature or request ♿ a11y When the issue or PR is related to accessibility labels Aug 25, 2026
@rkaraivanov
rkaraivanov merged commit bdeb272 into master Aug 25, 2026
4 checks passed
@rkaraivanov
rkaraivanov deleted the rkaraivanov/feat-add-a11y branch August 25, 2026 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🪛 enhancement New feature or request ♿ a11y When the issue or PR is related to accessibility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant