Skip to content

Accessibility fixes: text editor, group toggle, resize handle, reduced motion - #4246

Open
amanmahajan7 wants to merge 4 commits into
mainfrom
a11y-quick-fixes
Open

amanmahajan7 wants to merge 4 commits into
mainfrom
a11y-quick-fixes

Conversation

@amanmahajan7

Copy link
Copy Markdown
Collaborator

Summary

Small accessibility fixes from an audit of the grid against Chrome's Modern Web Guidance accessibility guides and the WAI-ARIA treegrid pattern. None of them change public APIs.

Changes

Text editor (renderTextEditor)

  • Accessible name: the input had none. It's now labeled with the column's name when that name is a string. Columns with a React element as their name still get no label, since there's no text to use.

  • Contrast in light mode:

    Before After Required
    Border #ccc, 1.61:1 #8f8f8f, 3.23:1 3:1 (WCAG 1.4.11)
    Placeholder #999, 2.85:1 #767676, 4.54:1 4.5:1 (WCAG 1.4.3)

    Dark mode keeps #ccc for the border (already 10:1) and #999 for the placeholder (already 5.65:1), using light-dark().

Group toggle (ToggleGroup / renderToggleGroup)

  • Was: a focusable <span> with no role, toggled only by Enter.
  • Now: a native <button type="button"> with all: unset. It gets the button role, focusability, and Enter/Space activation from the browser. The group cell still draws the focus outline.
  • aria-expanded stays on the group row only, where the treegrid pattern puts it ("on either the row element or on a cell"). Checked in Chromium's accessibility tree on the row grouping demo: the button reports no expanded state, and the rows do.
  • Click: the button toggles the group itself and stops the click from reaching the group cell, which would otherwise toggle it a second time. ToggleGroup is public, so it can't rely on the cell's handler: custom group cell renderers may use it in cells without one.
  • Shift+Space: blocked from activating the button, so it still selects the row.
  • Possible styling impact: apps that style .rdg-group-cell-content now style a <button> instead of a <span>.

Resize handle

  • Was: touch-action: none on the whole resizable header cell, so the grid couldn't be scrolled by touch from those headers.
  • Now: only the resize handle has it.
  • Why it was on the header: it was added in Refactor pointer events handling when resizing columns #2595, when the handle was a ::after pseudo-element of the header cell. Today the handle is its own element with its own pointer handlers.

Reduced motion

  • The sort arrow and group caret shape animations (transition: d 0.1s) now run only under @media (prefers-reduced-motion: no-preference).
  • The frozen-column shadow's opacity fade is unchanged, since a fade isn't the kind of motion this preference targets.

Testing

  • vp check and vp run typecheck pass.

  • New assertion: the editor's accessible name, in renderTextEditor.test.tsx.

  • Existing tests: TreeDataGrid, renderTextEditor and resizable pass in Chromium, Firefox and WebKit. The full Chromium browser suite passes, except 3 sorting tests that also fail on main on the same machine.

  • Group toggle, temporary test: checked every way to toggle, in all three browsers:

    • a mouse click on the button toggles once;
    • with the row focused, Right/Left Arrow expand and collapse;
    • with the button focused, Enter and Space toggle;
    • Shift+Space selects the row without toggling.

    I didn't commit it, because Space isn't required by the treegrid pattern; it works only because the toggle is now a native button.

  • Not tested automatically:

    • the touch-action move and the reduced-motion rules, which are CSS-only;
    • the screen reader output, which I checked by hand in Chromium's accessibility tree. The test suite's Chromium runs with --disable-renderer-accessibility.

🤖 Generated with Claude Code

… and motion

- Text editor: name the input after the column, and raise the border and
  placeholder contrast in light mode to 3.23:1 and 4.54:1
- Group toggle: render a native button instead of a focusable span, so it
  has a role and Enter/Space activation; the group row keeps aria-expanded
- Resize handle: limit touch-action: none to the handle, so the header can
  be scrolled by touch
- Only animate the sort and group carets without a reduced motion preference

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Oct 26, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 90.90909% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 99.23%. Comparing base (44945ff) to head (a4a62eb).

Files with missing lines Patch % Lines
src/cellRenderers/renderToggleGroup.tsx 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4246      +/-   ##
==========================================
- Coverage   99.27%   99.23%   -0.05%     
==========================================
  Files          44       44              
  Lines        2216     2221       +5     
  Branches      974      975       +1     
==========================================
+ Hits         2200     2204       +4     
- Misses         16       17       +1     
Files with missing lines Coverage Δ
src/HeaderCell.tsx 98.35% <100.00%> (-0.01%) ⬇️
src/editors/renderTextEditor.tsx 100.00% <100.00%> (ø)
src/sortStatus.tsx 100.00% <ø> (ø)
src/cellRenderers/renderToggleGroup.tsx 95.45% <88.88%> (-4.55%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@amanmahajan7
amanmahajan7 marked this pull request as ready for review October 27, 2026 14:36

return (
<span className={groupCellContentClassname} tabIndex={tabIndex} onKeyDown={handleKeyDown}>
<button

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The button does not cover the entire cell, could this be an accessibility issue?

Image

const caretClassname = `rdg-caret ${caret}`;

function handleKeyDown(event: React.KeyboardEvent<HTMLButtonElement>) {
// Shift + Space selects the row, so prevent it from activating the button

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the row is selected instead of the cell, we don't de/select the row, is that expected?

function handleClick(event: React.MouseEvent<HTMLButtonElement>) {
// the group cell also toggles the group on click
event.stopPropagation();
toggleGroup();

@nstepien nstepien Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • click on button
    • toggles the group
  • press space
    • toggles the group
  • arrow up + arrow down, back on the same row
  • press space
  • grid scrolls

The behavior is unexpected since visually it's the row that's focused, not the button.
Should we handle this on the cell itself?
Then we wouldn't need a button at all.

This branch has not been deployed

No deployments
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.

3 participants