-
Notifications
You must be signed in to change notification settings - Fork 860
Description
Reported by
@elastic/obs-exploration-team
Describe the bug
EuiSelectableList triggers an axe scrollable-region-focusable violation in non-virtualized mode. The .euiSelectableList__list wrapper <div> has overflow-y: auto applied via the euiYScrollWithShadows() mixin, but is given tabindex="-1" programmatically (via removeScrollableTabStop) and carries no accessible name or role. This makes the scrollable region unreachable by keyboard, violating the axe rule.
The virtualized path already handles this correctly — data-skip-axe="scrollable-region-focusable" is set on the FixedSizeList outer container. The non-virtualized path has no equivalent.
Impact and severity
- Axe severity: Serious
- End-user impact: Keyboard-only users cannot scroll the selectable list container in non-virtualized mode, potentially missing options that are off-screen.
- Workaround: Callers can exclude
.euiSelectableList__listfrom their axe scans, but this papers over the issue rather than fixing it.
Environment and versions
- EUI version: 113
- React version: 18
- Kibana version (if applicable): 9.4.0
- Browser: Chromium (via Playwright)
- Operating System: macOS
Minimum reproducible sandbox
Render an EuiSelectable with fewer items than the virtualization threshold (default: 100) and run axe against it. The EuiSelectable examples on eui.elastic.co should reproduce this directly — open any example with a short list and run axe.run() in the browser console.
To Reproduce
- Render an
EuiSelectablewith a small list (fewer than 100 items, so virtualization is not used) - Open the breakdown selector dropdown so the selectable list is visible
- Run axe against the rendered component (e.g. via
axe.run()in the console, or via Playwright +@axe-core/playwright) - Observe a
scrollable-region-focusableviolation reported on.euiSelectableList__list
Expected behavior
No scrollable-region-focusable violation. Either:
- The non-virtualized scroll wrapper receives
data-skip-axe="scrollable-region-focusable"for consistency with the virtualized path, or - The scroll wrapper is made genuinely keyboard-accessible by adding
tabIndex={0}and anaria-labelderived from the parentEuiSelectable's label or a new dedicated prop.
Screenshots (Optional)
Axe violation output from our Playwright a11y test:
Rule: scrollable-region-focusable. Impact: (serious)
Description: Ensure elements that have scrollable content are accessible by keyboard
Help: Scrollable region must have keyboard access
Nodes: 1. Selectors: .euiSelectableList__list
Additional context (Optional)
Relevant source locations:
- Scrollable styles applied:
selectable_list.styles.ts:42–49(euiYScrollWithShadows) tabindex="-1"assignment:selectable_list.tsx:222–228(removeScrollableTabStop)- Virtualized path axe skip (existing fix):
selectable_list.tsx:522 - Non-virtualized render (missing fix):
selectable_list.tsx:753–759