diff --git a/src/components/Select.vue b/src/components/Select.vue index c3ade5e7e..ab4b9a70b 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -1039,11 +1039,13 @@ 'aria-autocomplete': 'list', 'aria-labelledby': `vs${this.uid}__combobox`, 'aria-controls': `vs${this.uid}__listbox`, - 'aria-activedescendant': this.typeAheadPointer > -1 ? `vs${this.uid}__option-${this.typeAheadPointer}` : '', 'ref': 'search', 'type': 'search', 'autocomplete': this.autocomplete, 'value': this.search, + ...(this.dropdownOpen && this.filteredOptions[this.typeAheadPointer] ? { + 'aria-activedescendant': `vs${this.uid}__option-${this.typeAheadPointer}` + } : {}), }, events: { 'compositionstart': () => this.isComposing = true, diff --git a/tests/unit/Accessibility.spec.js b/tests/unit/Accessibility.spec.js new file mode 100644 index 000000000..793b76e43 --- /dev/null +++ b/tests/unit/Accessibility.spec.js @@ -0,0 +1,35 @@ +import { mountDefault } from "../helpers"; + +describe("Search Slot Scope", () => { + /** + * @see https://www.w3.org/WAI/PF/aria/states_and_properties#aria-activedescendant + */ + describe("aria-activedescendant", () => { + it("adds the active descendant attribute only when the dropdown is open and there is a typeAheadPointer value", async () => { + const Select = mountDefault(); + + expect( + Select.vm.scope.search.attributes["aria-activedescendant"] + ).toEqual(undefined); + + Select.vm.open = true; + await Select.vm.$nextTick(); + + expect( + Select.vm.scope.search.attributes["aria-activedescendant"] + ).toEqual(undefined); + }); + + it("adds the active descendant attribute when there's a typeahead value and an open dropdown", async () => { + const Select = mountDefault(); + + Select.vm.open = true; + Select.vm.typeAheadPointer = 1; + await Select.vm.$nextTick(); + + expect( + Select.vm.scope.search.attributes["aria-activedescendant"] + ).toEqual(`vs${Select.vm.uid}__option-1`); + }); + }); +});