Skip to content

ROU-12938: Fix keyboard navigation and screen reader support for group headers - #483

Open
os-davidlourenco wants to merge 5 commits into
sa-si-dev:masterfrom
os-davidlourenco:master
Open

ROU-12938: Fix keyboard navigation and screen reader support for group headers#483
os-davidlourenco wants to merge 5 commits into
sa-si-dev:masterfrom
os-davidlourenco:master

Conversation

@os-davidlourenco

Copy link
Copy Markdown
Contributor

Internal


What is the current behavior?

When multiple: true and option groups are enabled, group headers (.group-title rows) can be clicked to select or deselect all options in that group. However, those headers are excluded from keyboard navigation: arrow-key focus skips them, roving tabindex never lands on them, and Enter does not activate them when focused. They are also not clearly exposed to assistive technologies — selectable group headers do not get a descriptive aria-label, so screen reader users cannot discover or understand the group-level toggle the way pointer users can.

What is the new behavior?

Selectable group headers (multi-select with group checkboxes enabled) are now part of the same roving-focus flow as regular options. Arrow keys can move focus onto and off group titles, focused group titles receive tabindex="0", and Enter toggles selection for the whole group via the existing onGroupTitleClick logic. Selectable group headers also expose an aria-label that includes the group name and the select-all action text (e.g. "Option group 1, Select All"), so they are announced as interactive controls. Non-selectable group headers (single-select, or when disableOptionGroupCheckbox is set) continue to be skipped during navigation.

  • Include selectable group titles in roving tabindex and arrow-key navigation
  • Activate group select/deselect on Enter when a group title is focused
  • Add descriptive aria-label for selectable group headers
  • Add Cypress coverage for keyboard focus, arrow navigation, and Enter activation

Does this introduce a breaking change?

  • Yes
  • No

Other information

This is an accessibility fix only. Pointer behavior for group headers is unchanged. No new configuration options were added — selectable group headers reuse the existing selectAllText value in their aria-label.

@joselrio joselrio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, if I had to raise something I. would say we could also allow to use space to select an option. However this is more like a new improvement and not related with the work suggested here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Improves accessibility and keyboard interaction for option-group headers in VirtualSelect when multi-select group toggling is enabled, bringing group headers into the same roving-focus and activation model as options.

Changes:

  • Adds an aria-label for selectable group headers to make the group-level toggle discoverable to screen readers.
  • Centralizes “skip” logic for navigation so selectable group headers can participate in arrow-key focus while non-selectable headers remain skipped.
  • Enables Enter activation on focused selectable group headers by routing to existing onGroupTitleClick logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/virtual-select.js
Comment on lines +363 to 366
} else if (this.multiple) {
const groupLabel = this.secureText(Utils.getString(d.label));
ariaLabel = `aria-label="${groupLabel}, ${this.secureText(this.selectAllText)}"`;
}
Comment thread src/virtual-select.js
Comment on lines 3054 to +3056
selectFocusedOption() {
this.selectOption(this.$dropboxContainer.querySelector('.vscomp-option.focused'));
const $focusedEle = this.$dropboxContainer.querySelector('.vscomp-option.focused');

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