Skip to content

Commit 63dc45a

Browse files
authored
feat(QSelect): improve a11y for screen readers quasarframework#9304 (quasarframework#9983)
quasarframework#9304
1 parent 6aefde7 commit 63dc45a

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

ui/src/components/select/QSelect.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,15 @@ export default Vue.extend({
284284
dark: this.isOptionsDark
285285
}
286286

287+
const itemAttrs = {
288+
role: 'option',
289+
id: `${this.targetUid}_${index}`
290+
}
291+
287292
if (disable !== true) {
288293
this.isOptionSelected(opt) === true && (itemProps.active = true)
294+
itemAttrs['aria-selected'] = itemProps.active === true ? 'true' : 'false'
295+
289296
this.optionIndex === index && (itemProps.focused = true)
290297
}
291298

@@ -305,7 +312,8 @@ export default Vue.extend({
305312
focused: itemProps.focused,
306313
toggleOption: this.toggleOption,
307314
setOptionIndex: this.setOptionIndex,
308-
itemProps
315+
itemProps,
316+
itemAttrs
309317
}
310318

311319
if (options[i] === void 0 || isDeepEqual(option, options[i]) !== true) {
@@ -388,6 +396,23 @@ export default Vue.extend({
388396
return this.virtualScrollItemSize === void 0
389397
? (this.dense === true ? 24 : 48)
390398
: this.virtualScrollItemSize
399+
},
400+
401+
comboboxAttrs () {
402+
return {
403+
role: 'combobox',
404+
'aria-multiselectable': this.multiple === true ? 'true' : 'false',
405+
'aria-expanded': this.menu === true ? 'true' : 'false',
406+
'aria-owns': `${this.targetUid}_lb`,
407+
'aria-activedescendant': `${this.targetUid}_${this.optionIndex}`
408+
}
409+
},
410+
411+
listboxAttrs () {
412+
return {
413+
role: 'listbox',
414+
id: `${this.targetUid}_lb`
415+
}
391416
}
392417
},
393418

@@ -921,7 +946,8 @@ export default Vue.extend({
921946
staticClass: 'no-outline',
922947
attrs: {
923948
id: this.targetUid,
924-
tabindex: this.tabindex
949+
tabindex: this.tabindex,
950+
...this.comboboxAttrs
925951
},
926952
on: cache(this, 'f-tget', {
927953
keydown: this.__onTargetKeydown,
@@ -981,6 +1007,7 @@ export default Vue.extend({
9811007
: scope => h(QItem, {
9821008
key: scope.index,
9831009
props: scope.itemProps,
1010+
attrs: scope.itemAttrs,
9841011
on: scope.itemEvents
9851012
}, [
9861013
h(QItemSection, [
@@ -1038,7 +1065,8 @@ export default Vue.extend({
10381065
autocomplete: this.autocomplete,
10391066
'data-autofocus': fromDialog === true ? false : this.autofocus,
10401067
disabled: this.disable === true,
1041-
readonly: this.readonly === true
1068+
readonly: this.readonly === true,
1069+
...this.comboboxAttrs
10421070
},
10431071
on: this.inputControlEvents
10441072
}
@@ -1249,6 +1277,7 @@ export default Vue.extend({
12491277
transitionHide: this.transitionHide,
12501278
separateClosePopup: true
12511279
},
1280+
attrs: this.listboxAttrs,
12521281
on: cache(this, 'menu', {
12531282
'&scroll': this.__onVirtualScrollEvt,
12541283
'before-hide': this.__closeMenu,
@@ -1309,6 +1338,7 @@ export default Vue.extend({
13091338
staticClass: 'scroll',
13101339
class: this.menuContentClass,
13111340
style: this.popupContentStyle,
1341+
attrs: this.listboxAttrs,
13121342
on: cache(this, 'virtMenu', {
13131343
click: prevent,
13141344
'&scroll': this.__onVirtualScrollEvt

0 commit comments

Comments
 (0)