From 0841da6a041aa7d3800e28f41ed2c2c943628221 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Tue, 9 Mar 2021 10:47:10 -0500 Subject: [PATCH 01/14] Add keyboard navigation to dropdown menu --- lib/KDropdownMenu.vue | 25 +++++++++++++++---------- lib/keen/UiMenu.vue | 4 ++++ lib/keen/UiMenuOption.vue | 28 ++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index 6d4f3d354..9c9fbb79a 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -18,6 +18,7 @@ @open="handleOpen" > @@ -101,8 +102,12 @@ }, methods: { handleOpen() { + this.$nextTick(() => this.setFocus()); window.addEventListener('keyup', this.handleKeyUp, true); }, + setFocus() { + this.$refs.menu.$el.querySelector('li').focus(); + }, handleClose() { const focusedElement = document.activeElement; const popover = this.$refs.popover.$el; @@ -116,16 +121,16 @@ } window.removeEventListener('keyup', this.handleKeyUp, true); }, - handleKeyUp(event) { - if (event.shiftKey && event.keyCode == 9) { - const popover = this.$refs.popover.$el; - const popoverIsOpen = popover.clientWidth > 0 && popover.clientHeight > 0; - if (popoverIsOpen && !popover.contains(document.activeElement)) { - this.closePopover(); - this.focusOnButton(); - } - } - }, + // handleKeyUp(event) { + // if (event.shiftKey && event.keyCode == 9) { + // const popover = this.$refs.popover.$el; + // const popoverIsOpen = popover.clientWidth > 0 && popover.clientHeight > 0; + // if (popoverIsOpen && !popover.contains(document.activeElement)) { + // this.closePopover(); + // this.focusOnButton(); + // } + // } + // }, handleSelection(selection) { /** * Emitted when an option is selected diff --git a/lib/keen/UiMenu.vue b/lib/keen/UiMenu.vue index c2779e8ba..e2b1c9b6c 100644 --- a/lib/keen/UiMenu.vue +++ b/lib/keen/UiMenu.vue @@ -27,6 +27,7 @@ @keydown.enter.native="selectOption(option)" @keydown.esc.native.esc="closeMenu" + :style="[ activeOutline ]" > @@ -101,6 +102,9 @@ 'has-secondary-text': this.hasSecondaryText, }; }, + activeOutline() { + return this.isActive ? this.$coreOutline : {}; + }, }, methods: { diff --git a/lib/keen/UiMenuOption.vue b/lib/keen/UiMenuOption.vue index 278ce90ad..bde99afa8 100644 --- a/lib/keen/UiMenuOption.vue +++ b/lib/keen/UiMenuOption.vue @@ -9,6 +9,10 @@ :href="isAnchor ? (disabled ? null : href) : null" :tabindex="(isDivider || isAnchor || disabled) ? null : '0'" :target="isAnchor ? (disabled ? null : target) : null" + @focus="onFocus" + @blur="onBlur" + :style="isActive ? this.activeStyles : {}" + >
@@ -68,6 +72,12 @@ }, }, + data() { + return { + isActive: false, + }; + }, + computed: { classes() { return { @@ -84,7 +94,20 @@ isAnchor() { return !this.isDivider && this.href !== undefined; }, + activeStyles() { + return { ...this.$coreOutline, outlineOffset: '-2px' } + }, }, + methods: { + onFocus(e) { + this.isActive = true; + this.$emit('focus', e); + }, + onBlur(e) { + this.isActive = false; + this.$emit('blur', e); + }, + } }; @@ -125,6 +148,11 @@ background-color: $ui-menu-item-hover-color; } + &:focus:not(.is-disabled), + body[modality='keyboard'] &:focus { + background-color: $ui-menu-item-hover-color; + } + &.is-disabled { color: $secondary-text-color; cursor: default; From 481189c6c2e32218f3b7cd48aab6ad0730a873d0 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Tue, 9 Mar 2021 10:55:36 -0500 Subject: [PATCH 02/14] re-add commented out code, and remove unnecessary containFocus prop --- lib/KDropdownMenu.vue | 20 ++++++++++---------- lib/keen/UiMenu.vue | 5 +++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index 9c9fbb79a..706b9dc20 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -121,16 +121,16 @@ } window.removeEventListener('keyup', this.handleKeyUp, true); }, - // handleKeyUp(event) { - // if (event.shiftKey && event.keyCode == 9) { - // const popover = this.$refs.popover.$el; - // const popoverIsOpen = popover.clientWidth > 0 && popover.clientHeight > 0; - // if (popoverIsOpen && !popover.contains(document.activeElement)) { - // this.closePopover(); - // this.focusOnButton(); - // } - // } - // }, + handleKeyUp(event) { + if (event.shiftKey && event.keyCode == 9) { + const popover = this.$refs.popover.$el; + const popoverIsOpen = popover.clientWidth > 0 && popover.clientHeight > 0; + if (popoverIsOpen && !popover.contains(document.activeElement)) { + this.closePopover(); + this.focusOnButton(); + } + } + }, handleSelection(selection) { /** * Emitted when an option is selected diff --git a/lib/keen/UiMenu.vue b/lib/keen/UiMenu.vue index e2b1c9b6c..28f5c25f2 100644 --- a/lib/keen/UiMenu.vue +++ b/lib/keen/UiMenu.vue @@ -8,7 +8,6 @@ lazy :class="classes" - :contain-focus="containFocus" > Date: Tue, 16 Mar 2021 12:34:14 -0400 Subject: [PATCH 03/14] update code to use arrow keys for menu navigation --- lib/KDropdownMenu.vue | 29 +++++++++++++++++++---------- lib/keen/UiMenu.vue | 3 --- lib/keen/UiMenuOption.vue | 23 ----------------------- 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index 706b9dc20..40cffe629 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -98,12 +98,12 @@ }, }, beforeDestroy() { - window.removeEventListener('keyup', this.handleKeyUp, true); + window.removeEventListener('keydown', this.handleArrowKeys, true); }, methods: { handleOpen() { this.$nextTick(() => this.setFocus()); - window.addEventListener('keyup', this.handleKeyUp, true); + window.addEventListener('keydown', this.handleArrowKeys, true); }, setFocus() { this.$refs.menu.$el.querySelector('li').focus(); @@ -121,14 +121,23 @@ } window.removeEventListener('keyup', this.handleKeyUp, true); }, - handleKeyUp(event) { - if (event.shiftKey && event.keyCode == 9) { - const popover = this.$refs.popover.$el; - const popoverIsOpen = popover.clientWidth > 0 && popover.clientHeight > 0; - if (popoverIsOpen && !popover.contains(document.activeElement)) { - this.closePopover(); - this.focusOnButton(); - } + handleArrowKeys(event) { + // identify the menu state and length + const popover = this.$refs.popover.$el; + const menuElements = this.$refs.menu.$el.querySelector('div').children + const lastChild = menuElements[menuElements.length - 1] + const popoverIsOpen = popover.clientWidth > 0 && popover.clientHeight > 0; + // set current element and its siblings + let focusedElement = document.activeElement; + let sibling = focusedElement.nextElementSibling; + let prevSibling = focusedElement.previousElementSibling; + // manage rotating through the options + if (event.keyCode == 38 && popoverIsOpen) { + event.preventDefault() + prevSibling ? this.$nextTick(() => prevSibling.focus()) : this.$nextTick(() => lastChild.focus()) + } else if (event.keyCode == 40 && popoverIsOpen) { + event.preventDefault() + sibling ? this.$nextTick(() => sibling.focus()) : this.$nextTick(() => this.setFocus()); } }, handleSelection(selection) { diff --git a/lib/keen/UiMenu.vue b/lib/keen/UiMenu.vue index 28f5c25f2..6221d95b5 100644 --- a/lib/keen/UiMenu.vue +++ b/lib/keen/UiMenu.vue @@ -104,9 +104,6 @@ activeOutline() { return this.isActive ? this.$coreOutline : {}; }, - redirectFocus() { - console.log(document.activeElement) - }, }, methods: { diff --git a/lib/keen/UiMenuOption.vue b/lib/keen/UiMenuOption.vue index bde99afa8..4199dccba 100644 --- a/lib/keen/UiMenuOption.vue +++ b/lib/keen/UiMenuOption.vue @@ -9,10 +9,6 @@ :href="isAnchor ? (disabled ? null : href) : null" :tabindex="(isDivider || isAnchor || disabled) ? null : '0'" :target="isAnchor ? (disabled ? null : target) : null" - @focus="onFocus" - @blur="onBlur" - :style="isActive ? this.activeStyles : {}" - >
@@ -72,12 +68,6 @@ }, }, - data() { - return { - isActive: false, - }; - }, - computed: { classes() { return { @@ -94,20 +84,7 @@ isAnchor() { return !this.isDivider && this.href !== undefined; }, - activeStyles() { - return { ...this.$coreOutline, outlineOffset: '-2px' } - }, }, - methods: { - onFocus(e) { - this.isActive = true; - this.$emit('focus', e); - }, - onBlur(e) { - this.isActive = false; - this.$emit('blur', e); - }, - } }; From 321a649af614251a3dc8bb1f0790b65fef8bed19 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Tue, 16 Mar 2021 12:45:57 -0400 Subject: [PATCH 04/14] fix linting --- lib/KDropdownMenu.vue | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index 40cffe629..1c50d1a24 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -122,10 +122,10 @@ window.removeEventListener('keyup', this.handleKeyUp, true); }, handleArrowKeys(event) { - // identify the menu state and length + // identify the menu state and length const popover = this.$refs.popover.$el; - const menuElements = this.$refs.menu.$el.querySelector('div').children - const lastChild = menuElements[menuElements.length - 1] + const menuElements = this.$refs.menu.$el.querySelector('div').children; + const lastChild = menuElements[menuElements.length - 1]; const popoverIsOpen = popover.clientWidth > 0 && popover.clientHeight > 0; // set current element and its siblings let focusedElement = document.activeElement; @@ -133,10 +133,12 @@ let prevSibling = focusedElement.previousElementSibling; // manage rotating through the options if (event.keyCode == 38 && popoverIsOpen) { - event.preventDefault() - prevSibling ? this.$nextTick(() => prevSibling.focus()) : this.$nextTick(() => lastChild.focus()) + event.preventDefault(); + prevSibling + ? this.$nextTick(() => prevSibling.focus()) + : this.$nextTick(() => lastChild.focus()); } else if (event.keyCode == 40 && popoverIsOpen) { - event.preventDefault() + event.preventDefault(); sibling ? this.$nextTick(() => sibling.focus()) : this.$nextTick(() => this.setFocus()); } }, From 4d794ce8634b8c1665a931b2fe5de42b2b3481e2 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Thu, 12 May 2022 11:17:57 -0400 Subject: [PATCH 05/14] Fix tab navigation in popover. Tabbing does not move between menu options, but rather advances to next element in tab order --- lib/KDropdownMenu.vue | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index 1c50d1a24..fcc96cb5e 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -103,7 +103,7 @@ methods: { handleOpen() { this.$nextTick(() => this.setFocus()); - window.addEventListener('keydown', this.handleArrowKeys, true); + window.addEventListener('keydown', this.handleOpenMenuNavigation, true); }, setFocus() { this.$refs.menu.$el.querySelector('li').focus(); @@ -121,8 +121,11 @@ } window.removeEventListener('keyup', this.handleKeyUp, true); }, - handleArrowKeys(event) { + handleOpenMenuNavigation(event) { // identify the menu state and length + if (!this.$refs.popover && !this.$refs.popover.$el) { + return + } const popover = this.$refs.popover.$el; const menuElements = this.$refs.menu.$el.querySelector('div').children; const lastChild = menuElements[menuElements.length - 1]; @@ -140,6 +143,9 @@ } else if (event.keyCode == 40 && popoverIsOpen) { event.preventDefault(); sibling ? this.$nextTick(() => sibling.focus()) : this.$nextTick(() => this.setFocus()); + // if a tab key, not an arrow key, close the popover and advance to next item in the tab index + } else if (event.keyCode == 9 && popoverIsOpen) { + this.closePopover() } }, handleSelection(selection) { From 2361a8427c3f284d74ef403b9db6b98438d40918 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Thu, 12 May 2022 11:18:48 -0400 Subject: [PATCH 06/14] Add keyboard modality support for UiMenuOption and so works --- lib/keen/UiMenuOption.vue | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/keen/UiMenuOption.vue b/lib/keen/UiMenuOption.vue index 4199dccba..4f6cb6cf6 100644 --- a/lib/keen/UiMenuOption.vue +++ b/lib/keen/UiMenuOption.vue @@ -3,9 +3,12 @@ import UiIcon from './UiIcon.vue'; + import globalThemeState from '../styles/globalThemeState'; + export default { name: 'UiMenuOption', @@ -49,6 +54,10 @@ UiIcon, }, + data:() => ({ + isActive: false, + }), + props: { type: String, label: String, @@ -77,6 +86,9 @@ }; }, + activeStyle() { + return this.isActive ? {...this.$coreOutline, outlineOffset: '-2px' } : {} + }, isDivider() { return this.type === 'divider'; }, From 07ca4ef532d5c63e9478283be4c079642df3508b Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Thu, 12 May 2022 11:23:25 -0400 Subject: [PATCH 07/14] fix linting --- lib/KDropdownMenu.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index fcc96cb5e..9558e9f26 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -124,7 +124,7 @@ handleOpenMenuNavigation(event) { // identify the menu state and length if (!this.$refs.popover && !this.$refs.popover.$el) { - return + return; } const popover = this.$refs.popover.$el; const menuElements = this.$refs.menu.$el.querySelector('div').children; @@ -145,7 +145,7 @@ sibling ? this.$nextTick(() => sibling.focus()) : this.$nextTick(() => this.setFocus()); // if a tab key, not an arrow key, close the popover and advance to next item in the tab index } else if (event.keyCode == 9 && popoverIsOpen) { - this.closePopover() + this.closePopover(); } }, handleSelection(selection) { From e4b530adb837505c19080dd49dbad9d8de147519 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Thu, 12 May 2022 13:39:32 -0400 Subject: [PATCH 08/14] Revert some changes to trackInputModality, but add new options to better manage keyboard event focus by default on interactive elements, while allowing explicit support for keyboard navigation --- lib/styles/trackInputModality.js | 81 +++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/lib/styles/trackInputModality.js b/lib/styles/trackInputModality.js index 2e91577e9..168744142 100644 --- a/lib/styles/trackInputModality.js +++ b/lib/styles/trackInputModality.js @@ -7,15 +7,71 @@ import globalThemeState from './globalThemeState'; -// only keys listed here will change modality to keyboard -const KEYS_WHITELIST = ['Tab']; - function setUpEventHandlers(disableFocusRingByDefault) { - let recentKeyboardEvent = null; + let hadKeyboardEvent = false; + const keyboardModalityWhitelist = [ + 'input:not([type])', + 'input[type=text]', + 'input[type=checkbox]', + 'input[type=number]', + 'input[type=date]', + 'input[type=time]', + 'input[type=datetime]', + 'textarea', + '[role=textbox]', + 'a', + 'button', + ].join(','); + + // add this to any element to allow keyboard navigation, regardless of focus event + const keyboardModalityOverride = [ + '[supports-modality=keyboard]', + ]; + let isHandlingKeyboardThrottle; + const matcher = (() => { + const el = document.body; + + if (el.matchesSelector) { + return el.matchesSelector; + } + + if (el.webkitMatchesSelector) { + return el.webkitMatchesSelector; + } + + if (el.mozMatchesSelector) { + return el.mozMatchesSelector; + } + + if (el.msMatchesSelector) { + return el.msMatchesSelector; + } + })(); + + const focusTriggersKeyboardModality = function (el) { + let triggers = false; + + if (matcher) { + triggers = + matcher.call(el, keyboardModalityWhitelist) && matcher.call(el, ':not([readonly])') + } + return triggers; + }; + + const focusSetExplicitly = function (el) { + let triggers = false; + + if (matcher) { + triggers = + matcher.call(el, keyboardModalityOverride) && matcher.call(el, ':not([readonly])') + } + return triggers; + }; + if (disableFocusRingByDefault) { - const css = 'body:not([modality=keyboard]) :focus { outline: none; }'; + const css = 'body :focus:not([modality=keyboard]) { outline: none; }'; const head = document.head || document.getElementsByTagName('head')[0]; const style = document.createElement('style'); @@ -33,15 +89,15 @@ function setUpEventHandlers(disableFocusRingByDefault) { document.body.addEventListener( 'keydown', - event => { - recentKeyboardEvent = event; + () => { + hadKeyboardEvent = true; if (isHandlingKeyboardThrottle) { clearTimeout(isHandlingKeyboardThrottle); } isHandlingKeyboardThrottle = setTimeout(() => { - recentKeyboardEvent = null; + hadKeyboardEvent = false; }, 100); }, true @@ -49,8 +105,9 @@ function setUpEventHandlers(disableFocusRingByDefault) { document.body.addEventListener( 'focus', - () => { - if (recentKeyboardEvent && KEYS_WHITELIST.includes(recentKeyboardEvent.key)) { + e => { + console.log(hadKeyboardEvent, e, e.target, focusTriggersKeyboardModality(e.target) ) + if ((hadKeyboardEvent && focusTriggersKeyboardModality(e.target)) || focusSetExplicitly(e.target)) { globalThemeState.inputModality = 'keyboard'; } }, @@ -76,8 +133,8 @@ function setUpEventHandlers(disableFocusRingByDefault) { export default function trackInputModality({ disableFocusRingByDefault = true } = {}) { // skip for SSR if (typeof document !== 'undefined') { - document.addEventListener('DOMContentLoaded', function() { + document.addEventListener('DOMContentLoaded', function () { setUpEventHandlers(disableFocusRingByDefault); }); } -} +} \ No newline at end of file From 65fe3a801a5d2421b57ac35fdb8b2ff907f78da7 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Thu, 12 May 2022 17:29:55 -0400 Subject: [PATCH 09/14] Manage 'clicks' separately based on mouseup vs. keyboard presses --- lib/styles/trackInputModality.js | 33 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/styles/trackInputModality.js b/lib/styles/trackInputModality.js index 168744142..f299bfbc6 100644 --- a/lib/styles/trackInputModality.js +++ b/lib/styles/trackInputModality.js @@ -9,9 +9,11 @@ import globalThemeState from './globalThemeState'; function setUpEventHandlers(disableFocusRingByDefault) { let hadKeyboardEvent = false; - const keyboardModalityWhitelist = [ + let hadClickEvent = false; + const keyboardModalityDefaultElements = [ 'input:not([type])', 'input[type=text]', + 'input[type=radio]', 'input[type=checkbox]', 'input[type=number]', 'input[type=date]', @@ -24,9 +26,7 @@ function setUpEventHandlers(disableFocusRingByDefault) { ].join(','); // add this to any element to allow keyboard navigation, regardless of focus event - const keyboardModalityOverride = [ - '[supports-modality=keyboard]', - ]; + const keyboardModalityOverride = ['[supports-modality=keyboard]']; let isHandlingKeyboardThrottle; @@ -50,22 +50,21 @@ function setUpEventHandlers(disableFocusRingByDefault) { } })(); - const focusTriggersKeyboardModality = function (el) { + const focusTriggersKeyboardModality = function(el) { let triggers = false; if (matcher) { triggers = - matcher.call(el, keyboardModalityWhitelist) && matcher.call(el, ':not([readonly])') + matcher.call(el, keyboardModalityDefaultElements) && matcher.call(el, ':not([readonly])'); } return triggers; }; - const focusSetExplicitly = function (el) { + const focusSetExplicitly = function(el) { let triggers = false; if (matcher) { - triggers = - matcher.call(el, keyboardModalityOverride) && matcher.call(el, ':not([readonly])') + triggers = matcher.call(el, keyboardModalityOverride) && matcher.call(el, ':not([readonly])'); } return triggers; }; @@ -91,6 +90,7 @@ function setUpEventHandlers(disableFocusRingByDefault) { 'keydown', () => { hadKeyboardEvent = true; + hadClickEvent = false; if (isHandlingKeyboardThrottle) { clearTimeout(isHandlingKeyboardThrottle); @@ -103,11 +103,18 @@ function setUpEventHandlers(disableFocusRingByDefault) { true ); + document.body.addEventListener('mouseup', () => { + hadClickEvent = true; + hadKeyboardEvent = false; + }); + document.body.addEventListener( 'focus', e => { - console.log(hadKeyboardEvent, e, e.target, focusTriggersKeyboardModality(e.target) ) - if ((hadKeyboardEvent && focusTriggersKeyboardModality(e.target)) || focusSetExplicitly(e.target)) { + if ( + (hadKeyboardEvent && focusTriggersKeyboardModality(e.target)) || + (focusSetExplicitly(e.target) && !hadClickEvent) + ) { globalThemeState.inputModality = 'keyboard'; } }, @@ -133,8 +140,8 @@ function setUpEventHandlers(disableFocusRingByDefault) { export default function trackInputModality({ disableFocusRingByDefault = true } = {}) { // skip for SSR if (typeof document !== 'undefined') { - document.addEventListener('DOMContentLoaded', function () { + document.addEventListener('DOMContentLoaded', function() { setUpEventHandlers(disableFocusRingByDefault); }); } -} \ No newline at end of file +} From f60af8012bb75a54d52861c98b94149f12fac566 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Wed, 18 May 2022 10:34:04 -0400 Subject: [PATCH 10/14] Revert test changes; update git: reference to https: in yarn.lock --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 72f208600..fd34fe893 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9060,7 +9060,7 @@ knuth-shuffle-seeded@^1.0.6: "kolibri-design-system@git://github.com/learningequality/kolibri-design-system#65ee3a69a2ab072ea92e034d95118687678b4f5f": version "0.2.2-beta-2" - resolved "git://github.com/learningequality/kolibri-design-system#65ee3a69a2ab072ea92e034d95118687678b4f5f" + resolved "https://github.com/learningequality/kolibri-design-system#65ee3a69a2ab072ea92e034d95118687678b4f5f" dependencies: aphrodite "https://github.com/learningequality/aphrodite/" autosize "^3.0.21" From 2ee8772b2f805e5a298ef06d7f110105855fa376 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Thu, 19 May 2022 20:11:04 -0400 Subject: [PATCH 11/14] Switch to event.key reference, using .keyCode as fallback only --- lib/KDropdownMenu.vue | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index 9558e9f26..dbf9413ad 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -98,7 +98,7 @@ }, }, beforeDestroy() { - window.removeEventListener('keydown', this.handleArrowKeys, true); + window.removeEventListener('keydown', this.handleOpenMenuNavigation, true); }, methods: { handleOpen() { @@ -134,17 +134,21 @@ let focusedElement = document.activeElement; let sibling = focusedElement.nextElementSibling; let prevSibling = focusedElement.previousElementSibling; - // manage rotating through the options - if (event.keyCode == 38 && popoverIsOpen) { + + // manage rotating through the options using arrow keys + // UP arrow: .keyCode is depricated and should used only as a fallback + console.log(event.key); + if ((event.key == 'ArrowUp' || event.keyCode == 38) && popoverIsOpen) { event.preventDefault(); prevSibling ? this.$nextTick(() => prevSibling.focus()) : this.$nextTick(() => lastChild.focus()); - } else if (event.keyCode == 40 && popoverIsOpen) { + // DOWN arrow + } else if ((event.key == 'ArrowDown' || event.keyCode == 40) && popoverIsOpen) { event.preventDefault(); sibling ? this.$nextTick(() => sibling.focus()) : this.$nextTick(() => this.setFocus()); - // if a tab key, not an arrow key, close the popover and advance to next item in the tab index - } else if (event.keyCode == 9 && popoverIsOpen) { + // if a TAB key, not an arrow key, close the popover and advance to next item in the tab index + } else if ((event.key == 'Tab' || event.keyCode == 9) && popoverIsOpen) { this.closePopover(); } }, From 8dc1b3dd4526ffb1bd0862df66f6893d39ff9912 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Thu, 19 May 2022 20:11:59 -0400 Subject: [PATCH 12/14] Ensure both JS state and the body attribute are set for keyboard modality --- lib/styles/trackInputModality.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/styles/trackInputModality.js b/lib/styles/trackInputModality.js index f299bfbc6..6f395997e 100644 --- a/lib/styles/trackInputModality.js +++ b/lib/styles/trackInputModality.js @@ -70,7 +70,7 @@ function setUpEventHandlers(disableFocusRingByDefault) { }; if (disableFocusRingByDefault) { - const css = 'body :focus:not([modality=keyboard]) { outline: none; }'; + const css = 'body:not([modality=keyboard]) :focus { outline: none; }'; const head = document.head || document.getElementsByTagName('head')[0]; const style = document.createElement('style'); @@ -115,7 +115,12 @@ function setUpEventHandlers(disableFocusRingByDefault) { (hadKeyboardEvent && focusTriggersKeyboardModality(e.target)) || (focusSetExplicitly(e.target) && !hadClickEvent) ) { + // both the JS state and the body attribute for keyboard modality globalThemeState.inputModality = 'keyboard'; + document.body.setAttribute('modality', 'keyboard'); + } else { + globalThemeState.inputModality = null; + document.body.setAttribute('modality', ''); } }, true From 8cdef9188b6bdf4a9f1836e3879cc534ebb8eeb1 Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Fri, 20 May 2022 17:48:30 -0400 Subject: [PATCH 13/14] Resolve feedback --- lib/styles/trackInputModality.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/styles/trackInputModality.js b/lib/styles/trackInputModality.js index 6f395997e..fc3fb7862 100644 --- a/lib/styles/trackInputModality.js +++ b/lib/styles/trackInputModality.js @@ -103,7 +103,7 @@ function setUpEventHandlers(disableFocusRingByDefault) { true ); - document.body.addEventListener('mouseup', () => { + document.body.addEventListener('mousedown', () => { hadClickEvent = true; hadKeyboardEvent = false; }); @@ -130,6 +130,7 @@ function setUpEventHandlers(disableFocusRingByDefault) { 'blur', () => { globalThemeState.inputModality = null; + document.body.setAttribute('modality', ''); }, true ); From fcb8cb080865a89bc702bd028740c980229c543e Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Tue, 24 May 2022 09:30:39 -0400 Subject: [PATCH 14/14] Remove console --- lib/KDropdownMenu.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/KDropdownMenu.vue b/lib/KDropdownMenu.vue index dbf9413ad..e00a6fbb2 100644 --- a/lib/KDropdownMenu.vue +++ b/lib/KDropdownMenu.vue @@ -137,7 +137,6 @@ // manage rotating through the options using arrow keys // UP arrow: .keyCode is depricated and should used only as a fallback - console.log(event.key); if ((event.key == 'ArrowUp' || event.keyCode == 38) && popoverIsOpen) { event.preventDefault(); prevSibling