Skip to content

feat(data-grid): add cell/row accessibility prop callbacks - #1196

Open
hovoaep wants to merge 1 commit into
glideapps:mainfrom
hovoaep:feat/cell-row-accessibility-props
Open

feat(data-grid): add cell/row accessibility prop callbacks#1196
hovoaep wants to merge 1 commit into
glideapps:mainfrom
hovoaep:feat/cell-row-accessibility-props

Conversation

@hovoaep

@hovoaep hovoaep commented Aug 3, 2026

Copy link
Copy Markdown

Problem

The hidden accessibility <table> tree rendered alongside the canvas (used by screen readers) offered no way to customize its markup per cell/row, and had an unrelated correctness bug for custom cells:

  1. No a11y customization hooks. The <td>/<tr> elements in the accessibility tree only ever got the grid's built-in attributes (role, aria-selected, aria-readonly, aria-rowindex, etc.). There was no way for consumers to add supplemental aria-* attributes (e.g. aria-label, aria-describedby) to a specific cell or row.
  2. Custom cells never used their renderer's accessibility string. getRowData special-cased GridCellKind.Custom to always return cell.copyData, without ever asking the resolved CustomRenderer for a proper accessible description — and CustomRenderer didn't even expose a getAccessibilityString field to ask for.

Repro

  • Register a CustomRenderer with a getAccessibilityString implementation and render a Custom cell → the accessibility <td> text content is always copyData, the renderer's string is silently ignored.
  • Try to attach an aria-label to an individual cell or row → no prop exists for it; DataGridProps only exposes grid-wide callbacks (getCellContent, getRowThemeOverride, etc.), none scoped to a11y markup.

Fix

  1. Add getCellAccessibilityProps?: (cell: Item) => React.TdHTMLAttributes<HTMLTableCellElement> and getRowAccessibilityProps?: (row: number) => React.HTMLAttributes<HTMLTableRowElement> to DataGridProps, threaded through the full render chain: DataGridDndScrollingDataGridDataGridSearchDataEditor.
  2. Spread order matters. Caller-supplied props are spread after the grid's built-ins (role, aria-selected, aria-readonly, aria-rowindex) so consumers can override defaults, while props required for grid interactivity (id, onClick, onFocusCapture, ref, tabIndex) stay locked in after the spread.
  3. Custom cell accessibility string fix. Added optional getAccessibilityString?: (cell: T) => string to the CustomRenderer interface. getRowData now resolves the renderer first and uses its getAccessibilityString when defined, falling back to cell.copyData otherwise.

Test

New tests in test/data-grid.test.tsx:

  • getCellAccessibilityProps adds custom attributes and overrides a built-in (aria-readonly) on the a11y <td>.
  • getRowAccessibilityProps adds custom attributes and overrides a built-in (aria-rowindex) on the a11y <tr>.
  • Custom cell a11y string uses the renderer's getAccessibilityString when provided.
  • Custom cell a11y string falls back to copyData when the renderer has no getAccessibilityString.

Add getCellAccessibilityProps and getRowAccessibilityProps to spread
custom HTML attributes onto the hidden a11y <td>/<tr> elements,
threaded through DataGridDnd, ScrollingDataGrid, DataGridSearch, and
DataEditor. Caller-supplied props are placed after built-ins so they
can override defaults like aria-readonly/aria-rowindex.

Also fix custom cell a11y string: CustomRenderer.getAccessibilityString
is used when defined, falling back to cell.copyData otherwise.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant