Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/eui/changelogs/upcoming/9223.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**Accessibility**
- Improved the accessibility of `EuiSelectable` by removing empty `aria-activedescendant` attribute when no option is active to ensure the search input is perceivable by screen readers
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ describe('EuiFilterGroup multiselect example', () => {
cy.realPress('Enter');
cy.get('div[data-test-subj="euiSelectableList"]').should('exist');
cy.realPress('Tab');
cy.repeatRealPress('ArrowDown', 3);
cy.repeatRealPress('ArrowDown', 4);
cy.realPress('Enter');
cy.get('li[aria-selected="true"]')
.find('span.euiSelectableListItem__text')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,6 @@ exports[`EuiSelectable search value supports inheriting initialSearchValue from
</span>
</div>
<input
aria-activedescendant=""
aria-describedby="generated-id_instructions"
aria-haspopup="listbox"
aria-label="Filter options"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ describe('EuiSelectable', () => {
const onChange = cy.stub();
cy.realMount(<EuiSelectableWithSearchInput onChange={onChange} />);
cy.realPress('Tab');
cy.realPress('ArrowDown');
cy.realPress('Enter').then(() => {
expect(onChange).to.have.been.calledWith([
{ ...options[0], checked: 'on' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export const WithSearch: Story = {
// setting up for easier testing/QA
searchProps: {
'data-test-subj': 'selectableSearchHere',
'aria-label': 'Filter options',
},
},
render: ({ ...args }: EuiSelectableProps) => <StatefulSelectable {...args} />,
Expand Down
11 changes: 10 additions & 1 deletion packages/eui/src/components/selectable/selectable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ export class EuiSelectable<T = {}> extends Component<
return;
}

if (event && this.props.searchable && event.target === this.inputRef) {
this.setState({ isFocused: true });
return;
}

if (
!this.state.visibleOptions.length ||
this.state.activeOptionIndex != null
Expand Down Expand Up @@ -750,7 +755,11 @@ export class EuiSelectable<T = {}> extends Component<
value={searchValue}
onChange={this.onSearchChange}
listId={this.optionsListRef.current ? this.listId : undefined} // Only pass the listId if it exists on the page
aria-activedescendant={this.makeOptionId(activeOptionIndex)} // the current faux-focused option
aria-activedescendant={
activeOptionIndex != null
? this.makeOptionId(activeOptionIndex)
: undefined
}
placeholder={placeholderName}
isPreFiltered={!!isPreFiltered}
optionMatcher={optionMatcher!}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ exports[`EuiSelectableTemplateSitewide is rendered 1`] = `
</span>
</div>
<input
aria-activedescendant=""
aria-describedby="generated-id_instructions"
aria-haspopup="listbox"
aria-label="aria-label"
Expand Down Expand Up @@ -107,7 +106,6 @@ exports[`EuiSelectableTemplateSitewide props popoverFooter is rendered 1`] = `
</span>
</div>
<input
aria-activedescendant=""
aria-describedby="generated-id_instructions"
aria-haspopup="listbox"
aria-label="Filter options"
Expand Down Expand Up @@ -162,7 +160,6 @@ exports[`EuiSelectableTemplateSitewide props popoverProps is rendered 1`] = `
</span>
</div>
<input
aria-activedescendant=""
aria-describedby="generated-id_instructions"
aria-haspopup="listbox"
aria-label="Filter options"
Expand Down Expand Up @@ -217,7 +214,6 @@ exports[`EuiSelectableTemplateSitewide props popoverTitle is rendered 1`] = `
</span>
</div>
<input
aria-activedescendant=""
aria-describedby="generated-id_instructions"
aria-haspopup="listbox"
aria-label="Filter options"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export default () => {
searchable
searchProps={{
'data-test-subj': 'selectableSearchHere',
'aria-label': 'Filter options',
}}
options={options}
onChange={(newOptions) => setOptions(newOptions)}
Expand Down