Summary
When editing a multi-value ad hoc filter (=| / !=|), the Apply button that commits the
selection is rendered inside an aria-hidden="true" subtree. Screen reader users are never told
it exists, and it also has tabIndex={-1}, so it cannot be reached with the keyboard either.
This is pre-existing behaviour, not caused by any recent change.
Reproduce
- Render an
AdHocFiltersVariable with layout: 'combobox' and supportsMultiValueOperators: true.
- Click a filter pill that uses the
one of (=|) operator to open the values dropdown.
- Inspect the accessibility tree, or query the button by role.
Actual
The button's wrapper (multiValueApplyWrapper in DropdownItem.tsx) carries aria-hidden="true",
so the button is absent from the accessibility tree. An ariaSnapshot of the open dropdown lists
the options but no button at all:
- option "All" [selected]:
- checkbox
- option "AMER":
- checkbox
- option "APAC":
- checkbox [checked]
- option "EMEA":
- checkbox [checked]
- option "LATAM":
- checkbox
Correspondingly, page.getByRole('button', { name: 'Apply' }) never resolves in a real browser;
only a text locator finds it.
Expected
The Apply button is exposed to assistive technology and reachable by keyboard, like any other
control in the dropdown.
Severity
Moderate rather than blocking. The selection can still be committed from the keyboard — Tab
commits multi-value edits (AdHocFiltersCombobox.tsx, the Tab branch of the input's keydown
handler), which I confirmed works: arrowing to a value, pressing Enter to tick it, then Tab
updated the filter to region=~"EMEA|APAC|AMER". But that path is undiscoverable, and the visible
affordance sighted users rely on is never announced.
Likely cause
MultiValueApplyButton is rendered inside FloatingFocusManager but outside the floating
element — it is a sibling that positions itself with a transform derived from
refs.floating.current. FloatingFocusManager defaults to modal mode, which marks everything
outside the floating node as aria-hidden, and the wrapper gets caught in that sweep.
Consistent with that: opening the dropdown takes the document from 4 to 21 elements with
aria-hidden="true", covering the page header, the other filter pills and the surrounding
content — the usual markOthers behaviour.
Suggested fix
Render the Apply button inside the floating element rather than as a sibling of it, so it falls
within the focus manager's floating node. That would also remove the manual
getBoundingClientRect positioning. Failing that, opting the wrapper out of the hiding sweep and
giving the button a real tab stop would work, though it leaves the focus-order oddity in place.
Note for whoever fixes this
The existing jsdom tests locate the button with getByRole('button', { name: 'Apply' }) and pass,
because jsdom does not reproduce floating-ui's aria-hidden handling. A regression test therefore
needs either a real browser or a direct assertion that the wrapper is not inside an
aria-hidden subtree.
Summary
When editing a multi-value ad hoc filter (
=|/!=|), the Apply button that commits theselection is rendered inside an
aria-hidden="true"subtree. Screen reader users are never toldit exists, and it also has
tabIndex={-1}, so it cannot be reached with the keyboard either.This is pre-existing behaviour, not caused by any recent change.
Reproduce
AdHocFiltersVariablewithlayout: 'combobox'andsupportsMultiValueOperators: true.one of(=|) operator to open the values dropdown.Actual
The button's wrapper (
multiValueApplyWrapperinDropdownItem.tsx) carriesaria-hidden="true",so the button is absent from the accessibility tree. An
ariaSnapshotof the open dropdown liststhe options but no button at all:
Correspondingly,
page.getByRole('button', { name: 'Apply' })never resolves in a real browser;only a text locator finds it.
Expected
The Apply button is exposed to assistive technology and reachable by keyboard, like any other
control in the dropdown.
Severity
Moderate rather than blocking. The selection can still be committed from the keyboard —
Tabcommits multi-value edits (
AdHocFiltersCombobox.tsx, theTabbranch of the input'skeydownhandler), which I confirmed works: arrowing to a value, pressing
Enterto tick it, thenTabupdated the filter to
region=~"EMEA|APAC|AMER". But that path is undiscoverable, and the visibleaffordance sighted users rely on is never announced.
Likely cause
MultiValueApplyButtonis rendered insideFloatingFocusManagerbut outside the floatingelement — it is a sibling that positions itself with a
transformderived fromrefs.floating.current.FloatingFocusManagerdefaults to modal mode, which marks everythingoutside the floating node as
aria-hidden, and the wrapper gets caught in that sweep.Consistent with that: opening the dropdown takes the document from 4 to 21 elements with
aria-hidden="true", covering the page header, the other filter pills and the surroundingcontent — the usual
markOthersbehaviour.Suggested fix
Render the Apply button inside the floating element rather than as a sibling of it, so it falls
within the focus manager's floating node. That would also remove the manual
getBoundingClientRectpositioning. Failing that, opting the wrapper out of the hiding sweep andgiving the button a real tab stop would work, though it leaves the focus-order oddity in place.
Note for whoever fixes this
The existing jsdom tests locate the button with
getByRole('button', { name: 'Apply' })and pass,because jsdom does not reproduce floating-ui's
aria-hiddenhandling. A regression test thereforeneeds either a real browser or a direct assertion that the wrapper is not inside an
aria-hiddensubtree.