Skip to content

Commit 164ac68

Browse files
committed
Handle keyboard focus
Signed-off-by: Christopher Ng <chrng8@gmail.com>
1 parent 61f4211 commit 164ac68

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

src/components/Select.vue

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,11 @@
108108
isOptionDeselectable(option) && index === typeAheadPointer,
109109
'vs__dropdown-option--selected': isOptionSelected(option),
110110
'vs__dropdown-option--highlight': index === typeAheadPointer,
111+
'vs__dropdown-option--kb-focus': hasKeyboardFocusBorder(index),
111112
'vs__dropdown-option--disabled': !selectable(option),
112113
}"
113114
:aria-selected="optionAriaSelected(option)"
114-
@mouseover="selectable(option) ? (typeAheadPointer = index) : null"
115+
@mousemove="onMouseMove(option, index)"
115116
@click.prevent.stop="selectable(option) ? select(option) : null"
116117
>
117118
<slot name="option" v-bind="normalizeOptionForSlot(option)">
@@ -661,6 +662,15 @@ export default {
661662
},
662663
},
663664
665+
/**
666+
* Display a visible border around dropdown options
667+
* which have keyboard focus.
668+
*/
669+
keyboardFocusBorder: {
670+
type: Boolean,
671+
default: false,
672+
},
673+
664674
/**
665675
* A unique identifier used to generate IDs in HTML.
666676
* Must be unique for every instance of the component.
@@ -676,6 +686,7 @@ export default {
676686
search: '',
677687
open: false,
678688
isComposing: false,
689+
isKeyboardNavigation: false,
679690
pushedTags: [],
680691
// eslint-disable-next-line vue/no-reserved-keys
681692
_value: [], // Internal value managed by Vue Select if no `value` prop is passed
@@ -1135,6 +1146,19 @@ export default {
11351146
return this.isOptionSelected(option) && this.deselectFromDropdown
11361147
},
11371148
1149+
/**
1150+
* Check if the option at the given index should display a
1151+
* keyboard focus border.
1152+
* @param {Number} index
1153+
* @return {Boolean}
1154+
*/
1155+
hasKeyboardFocusBorder(index) {
1156+
if (this.keyboardFocusBorder && this.isKeyboardNavigation) {
1157+
return index === this.typeAheadPointer
1158+
}
1159+
return false
1160+
},
1161+
11381162
/**
11391163
* Determine if two option objects are matching.
11401164
*
@@ -1324,6 +1348,20 @@ export default {
13241348
this.mousedown = false
13251349
},
13261350
1351+
/**
1352+
* Event-Handler for option mousemove
1353+
* @param {Object|String} option
1354+
* @param {Number} index
1355+
* @return {void}
1356+
*/
1357+
onMouseMove(option, index) {
1358+
this.isKeyboardNavigation = false
1359+
if (!this.selectable(option)) {
1360+
return
1361+
}
1362+
this.typeAheadPointer = index
1363+
},
1364+
13271365
/**
13281366
* Search <input> KeyBoardEvent handler.
13291367
* @param {KeyboardEvent} e
@@ -1349,6 +1387,7 @@ export default {
13491387
// up.prevent
13501388
38: (e) => {
13511389
e.preventDefault()
1390+
this.isKeyboardNavigation = true
13521391
if (!this.open) {
13531392
this.open = true
13541393
return
@@ -1358,6 +1397,7 @@ export default {
13581397
// down.prevent
13591398
40: (e) => {
13601399
e.preventDefault()
1400+
this.isKeyboardNavigation = true
13611401
if (!this.open) {
13621402
this.open = true
13631403
return

0 commit comments

Comments
 (0)