From ac01c0f5f577ed449863f39a7402edcb7ccdef8e Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Thu, 12 Jan 2023 18:59:42 -0800 Subject: [PATCH 1/3] Handle keyboard focus Signed-off-by: Christopher Ng --- src/components/Select.vue | 42 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/components/Select.vue b/src/components/Select.vue index 222b4117..60c4e460 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -108,10 +108,11 @@ isOptionDeselectable(option) && index === typeAheadPointer, 'vs__dropdown-option--selected': isOptionSelected(option), 'vs__dropdown-option--highlight': index === typeAheadPointer, + 'vs__dropdown-option--kb-focus': hasKeyboardFocusBorder(index), 'vs__dropdown-option--disabled': !selectable(option), }" :aria-selected="optionAriaSelected(option)" - @mouseover="selectable(option) ? (typeAheadPointer = index) : null" + @mousemove="onMouseMove(option, index)" @click.prevent.stop="selectable(option) ? select(option) : null" > @@ -661,6 +662,15 @@ export default { }, }, + /** + * Display a visible border around dropdown options + * which have keyboard focus. + */ + keyboardFocusBorder: { + type: Boolean, + default: false, + }, + /** * A unique identifier used to generate IDs in HTML. * Must be unique for every instance of the component. @@ -676,6 +686,7 @@ export default { search: '', open: false, isComposing: false, + isKeyboardNavigation: false, pushedTags: [], // eslint-disable-next-line vue/no-reserved-keys _value: [], // Internal value managed by Vue Select if no `value` prop is passed @@ -1135,6 +1146,19 @@ export default { return this.isOptionSelected(option) && this.deselectFromDropdown }, + /** + * Check if the option at the given index should display a + * keyboard focus border. + * @param {Number} index + * @return {Boolean} + */ + hasKeyboardFocusBorder(index) { + if (this.keyboardFocusBorder && this.isKeyboardNavigation) { + return index === this.typeAheadPointer + } + return false + }, + /** * Determine if two option objects are matching. * @@ -1324,6 +1348,20 @@ export default { this.mousedown = false }, + /** + * Event-Handler for option mousemove + * @param {Object|String} option + * @param {Number} index + * @return {void} + */ + onMouseMove(option, index) { + this.isKeyboardNavigation = false + if (!this.selectable(option)) { + return + } + this.typeAheadPointer = index + }, + /** * Search KeyBoardEvent handler. * @param {KeyboardEvent} e @@ -1349,6 +1387,7 @@ export default { // up.prevent 38: (e) => { e.preventDefault() + this.isKeyboardNavigation = true if (!this.open) { this.open = true return @@ -1358,6 +1397,7 @@ export default { // down.prevent 40: (e) => { e.preventDefault() + this.isKeyboardNavigation = true if (!this.open) { this.open = true return From 73e0b042fa8ec2480c660b6a5002212cd0c5f342 Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Thu, 12 Jan 2023 19:04:03 -0800 Subject: [PATCH 2/3] Darken default dropdown active bg color - To meet WCAG AA contrast requirements Signed-off-by: Christopher Ng --- src/css/global/variables.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css/global/variables.css b/src/css/global/variables.css index 8847e150..f67df43d 100644 --- a/src/css/global/variables.css +++ b/src/css/global/variables.css @@ -54,7 +54,7 @@ --vs-dropdown-option-padding: 3px 20px; /* Active State */ - --vs-dropdown-option--active-bg: #5897fb; + --vs-dropdown-option--active-bg: #136cfb; --vs-dropdown-option--active-color: #fff; /* Deselect State */ From bc141b7b427d20d6b1a5e64e08a50d255ad855c5 Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Thu, 12 Jan 2023 19:06:03 -0800 Subject: [PATCH 3/3] Add CSS variable and class styles Signed-off-by: Christopher Ng --- src/css/global/variables.css | 3 +++ src/css/modules/dropdown-option.css | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/css/global/variables.css b/src/css/global/variables.css index f67df43d..34397108 100644 --- a/src/css/global/variables.css +++ b/src/css/global/variables.css @@ -57,6 +57,9 @@ --vs-dropdown-option--active-bg: #136cfb; --vs-dropdown-option--active-color: #fff; + /* Keyboard Focus State */ + --vs-dropdown-option--kb-focus-box-shadow: inset 0px 0px 0px 2px #949494; + /* Deselect State */ --vs-dropdown-option--deselect-bg: #fb5858; --vs-dropdown-option--deselect-color: #fff; diff --git a/src/css/modules/dropdown-option.css b/src/css/modules/dropdown-option.css index 0c16db46..e21a70bb 100644 --- a/src/css/modules/dropdown-option.css +++ b/src/css/modules/dropdown-option.css @@ -14,6 +14,10 @@ color: var(--vs-dropdown-option--active-color); } +.vs__dropdown-option--kb-focus { + box-shadow: var(--vs-dropdown-option--kb-focus-box-shadow); +} + .vs__dropdown-option--deselect { background: var(--vs-dropdown-option--deselect-bg); color: var(--vs-dropdown-option--deselect-color);