From d6837b7a5af8838945316aff35870c525f0c3753 Mon Sep 17 00:00:00 2001 From: Juraj Kapsiar Date: Mon, 24 Oct 2022 13:58:50 +0200 Subject: [PATCH] feat(what-input): Limit keyboard detection in inputs (#25087) * feat(what-input): Limit keyboard detection in inputs * show focus indicator in dropdown scenarios * fix test * set what-input to mouse initially * naming, docs and changelog * Update packages/fluentui/react-northstar/src/utils/whatInput.ts Co-authored-by: ling1726 Co-authored-by: Juraj Kapsiar Co-authored-by: ling1726 --- packages/fluentui/CHANGELOG.md | 1 + .../src/components/Dropdown/Dropdown.tsx | 11 ++++++++ .../react-northstar/src/utils/whatInput.ts | 27 +++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/fluentui/CHANGELOG.md b/packages/fluentui/CHANGELOG.md index 072f02d87b709..e11c9d19bc6e7 100644 --- a/packages/fluentui/CHANGELOG.md +++ b/packages/fluentui/CHANGELOG.md @@ -26,6 +26,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add a new comfy layout variation for `ChatMessage` @davezuko ([#23974](https://github.com/microsoft/fluentui/pull/23974)) - Add `FocusTrapZone` prop `preventScrollOnRestoreFocus` to prevent scroll on focus when `FocusTrapZone` releases @yuanboxue-amber ([#24632](https://github.com/microsoft/fluentui/pull/24632)) - Add new style to v0 Tooltip to match v9 Tooltip @GianoglioEnrico ([#24908](https://github.com/microsoft/fluentui/pull/24908)) +- Limit keyboard detection in inputs @jurokapsiar ([#25087](https://github.com/microsoft/fluentui/pull/25087)) ### Fixes - Allow React 17 in `peerDependencies` of all packages and bump react-is to 17 @TristanWatanabe ([#24356](https://github.com/microsoft/fluentui/pull/24356)) diff --git a/packages/fluentui/react-northstar/src/components/Dropdown/Dropdown.tsx b/packages/fluentui/react-northstar/src/components/Dropdown/Dropdown.tsx index 70ab574f0def0..70184de809ce0 100644 --- a/packages/fluentui/react-northstar/src/components/Dropdown/Dropdown.tsx +++ b/packages/fluentui/react-northstar/src/components/Dropdown/Dropdown.tsx @@ -35,6 +35,7 @@ import { UIComponentProps, isFromKeyboard as detectIsFromKeyboard, createShorthand, + setWhatInputSource, } from '../../utils'; import { List, ListProps } from '../List/List'; import { DropdownItem, DropdownItemProps } from './DropdownItem'; @@ -1167,12 +1168,22 @@ export const Dropdown = (React.forwardRef((props, case keyboardKey.ArrowLeft: e.stopPropagation(); if (!context.rtl) { + // https://github.com/testing-library/user-event/issues/709 + // JSDOM does not implement `event.view` so prune this code path in test + if (process.env.NODE_ENV !== 'test') { + setWhatInputSource(e.view.document, 'keyboard'); + } trySetLastSelectedItemAsActive(); } break; case keyboardKey.ArrowRight: e.stopPropagation(); if (context.rtl) { + // https://github.com/testing-library/user-event/issues/709 + // JSDOM does not implement `event.view` so prune this code path in test + if (process.env.NODE_ENV !== 'test') { + setWhatInputSource(e.view.document, 'keyboard'); + } trySetLastSelectedItemAsActive(); } break; diff --git a/packages/fluentui/react-northstar/src/utils/whatInput.ts b/packages/fluentui/react-northstar/src/utils/whatInput.ts index 422b1e5ea3e99..26b5685e4fff8 100644 --- a/packages/fluentui/react-northstar/src/utils/whatInput.ts +++ b/packages/fluentui/react-northstar/src/utils/whatInput.ts @@ -8,7 +8,7 @@ import { isBrowser } from './isBrowser'; */ // last used input type -let currentInput = 'initial'; +let currentInput = 'mouse'; // assume happy path // event buffer timer let eventTimer = null; @@ -108,6 +108,26 @@ const addListeners = (eventTarget: Window) => { eventTarget.addEventListener('keyup', eventBuffer, true); }; +/** + * + * @param document document to apply the update to + * @param eventKey keyboard key passed from the event + * @returns true if mode should be switched, false if not (when an input-like element is focused, and the key was not a navigational key) + */ +const keyboardInputFocused = (document: Document, eventKey: number) => { + if ( + document.activeElement.tagName === 'INPUT' || + document.activeElement.tagName === 'TEXTAREA' || + document.activeElement.getAttribute('contenteditable') + ) { + return ( + eventKey === 9 || // tab + eventKey === 117 + ); // F6 + } + return true; +}; + // checks conditions before updating new input const setInput = (event: WhatInputEvents) => { // only execute if the event buffer timer isn't running @@ -120,7 +140,10 @@ const setInput = (event: WhatInputEvents) => { } const ignoreMatch = ignoreMap.indexOf(eventKey) === -1; - const shouldUpdate = (value === 'keyboard' && eventKey && ignoreMatch) || value === 'mouse' || value === 'touch'; + const shouldUpdate = + (value === 'keyboard' && eventKey && ignoreMatch && keyboardInputFocused(event.view.document, eventKey)) || + value === 'mouse' || + value === 'touch'; if (currentInput !== value && shouldUpdate) { currentInput = value;