Skip to content

Commit 3d17871

Browse files
committed
1 parent 709905d commit 3d17871

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

src/components/Select.vue

+20-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
v-append-to-body
9292
class="vs__dropdown-menu"
9393
role="listbox"
94+
:aria-multiselectable="multiple"
9495
tabindex="-1"
9596
@mousedown.prevent="onMousedown"
9697
@mouseup="onMouseUp"
@@ -109,7 +110,7 @@
109110
'vs__dropdown-option--highlight': index === typeAheadPointer,
110111
'vs__dropdown-option--disabled': !selectable(option),
111112
}"
112-
:aria-selected="index === typeAheadPointer ? true : null"
113+
:aria-selected="optionAriaSelected(option, index)"
113114
@mouseover="selectable(option) ? (typeAheadPointer = index) : null"
114115
@click.prevent.stop="selectable(option) ? select(option) : null"
115116
>
@@ -1212,6 +1213,24 @@ export default {
12121213
)
12131214
},
12141215
1216+
/**
1217+
* Determine the `aria-selected` value
1218+
* of an option
1219+
*
1220+
* @param {Object|String} option
1221+
* @param {Number} index
1222+
* @return {null|boolean}
1223+
*/
1224+
optionAriaSelected(option, index) {
1225+
if (!this.selectable(option)) {
1226+
return null
1227+
}
1228+
if (this.multiple) {
1229+
return this.isOptionSelected(option)
1230+
}
1231+
return index === this.typeAheadPointer ? true : null
1232+
},
1233+
12151234
/**
12161235
* Ensures that options are always
12171236
* passed as objects to scoped slots.

tests/unit/Accessibility.spec.js

+60
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,63 @@ describe('UID', () => {
4545
expect(Select.find('#vs2__combobox').exists()).toBeTruthy()
4646
})
4747
})
48+
49+
describe('Option List', () => {
50+
it('multiselectable attribute should not be present by default', async () => {
51+
const Select = mountDefault()
52+
53+
Select.vm.open = true
54+
await Select.vm.$nextTick()
55+
56+
expect(
57+
Select.findComponent({ ref: 'dropdownMenu' }).attributes()[
58+
'aria-multiselectable'
59+
]
60+
).toBe(undefined)
61+
})
62+
63+
it('multiselectable attribute should be true when multiple is true', async () => {
64+
const Select = mountDefault({ multiple: true })
65+
66+
Select.vm.open = true
67+
await Select.vm.$nextTick()
68+
69+
expect(
70+
Select.findComponent({ ref: 'dropdownMenu' }).attributes()[
71+
'aria-multiselectable'
72+
]
73+
).toBe('true')
74+
})
75+
76+
it('selected attribute should be true on highlighted option only', async () => {
77+
const Select = mountDefault()
78+
79+
Select.vm.open = true
80+
await Select.vm.$nextTick()
81+
Select.vm.typeAheadDown()
82+
Select.vm.typeAheadDown()
83+
await Select.vm.$nextTick()
84+
85+
expect(
86+
Select.findAll('.vs__dropdown-option').wrappers.map(
87+
(option) => option.attributes()['aria-selected']
88+
)
89+
).toStrictEqual([undefined, 'true', undefined])
90+
})
91+
92+
it('selected attribute should be true on all selected options when multiple is true', async () => {
93+
const Select = mountDefault({
94+
multiple: true,
95+
value: ['one', 'two'],
96+
})
97+
98+
Select.vm.open = true
99+
await Select.vm.$nextTick()
100+
101+
expect(
102+
Select.findAll('.vs__dropdown-option').wrappers.map(
103+
(option) => option.attributes()['aria-selected']
104+
)
105+
).toStrictEqual(['true', 'true', undefined])
106+
})
107+
})

0 commit comments

Comments
 (0)