diff options
author | Mathieu Suen <mathieu.suen@sonarsource.com> | 2022-11-11 09:26:59 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-11-14 20:03:39 +0000 |
commit | 01c4dc5db1b4d64babbeb33e6a2d2be043fabeeb (patch) | |
tree | 01fe7598028829afc6f1b66b1b2ebfb1635e0ab6 | |
parent | 1a9f524c359d8e1bc099f150d1ca53c237c8c848 (diff) | |
download | sonarqube-01c4dc5db1b4d64babbeb33e6a2d2be043fabeeb.tar.gz sonarqube-01c4dc5db1b4d64babbeb33e6a2d2be043fabeeb.zip |
SONAR-17591 Fix keyboard arrow behavior in multi-line input
4 files changed, 37 insertions, 11 deletions
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx index beaccb76e96..e309c9a4af8 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx @@ -27,6 +27,7 @@ import withCurrentUserContext from '../../app/components/current-user/withCurren import { Location, Router, withRouter } from '../../components/hoc/withRouter'; import { getLeakValue } from '../../components/measure/utils'; import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../helpers/branch-like'; +import { isInput } from '../../helpers/keyboardEventHelpers'; import { KeyboardKeys } from '../../helpers/keycodes'; import { getStandards } from '../../helpers/security-standard'; import { BranchLike } from '../../types/branch-like'; @@ -147,6 +148,9 @@ export class SecurityHotspotsApp extends React.PureComponent<Props, State> { } handleKeyDown = (event: KeyboardEvent) => { + if (isInput(event)) { + return; + } if (event.key === KeyboardKeys.Alt) { event.preventDefault(); return; diff --git a/server/sonar-web/src/main/js/components/controls/UpDownKeyboardHandler.tsx b/server/sonar-web/src/main/js/components/controls/UpDownKeyboardHandler.tsx index faf70fc0ce6..874843ba02b 100644 --- a/server/sonar-web/src/main/js/components/controls/UpDownKeyboardHandler.tsx +++ b/server/sonar-web/src/main/js/components/controls/UpDownKeyboardHandler.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { isShortcut } from '../../helpers/keyboardEventHelpers'; +import { isShortcut, isTextarea } from '../../helpers/keyboardEventHelpers'; import { KeyboardKeys } from '../../helpers/keycodes'; interface Props { @@ -47,7 +47,7 @@ export default class UpDownKeyboardHanlder extends React.PureComponent< } handleKeyboard = (event: KeyboardEvent) => { - if (isShortcut(event)) { + if (isShortcut(event) || isTextarea(event)) { return true; } switch (event.key) { @@ -67,7 +67,7 @@ export default class UpDownKeyboardHanlder extends React.PureComponent< getFocusableElement() { const { containerClass = 'popup' } = this.props; - const focussableElements = `.${containerClass} a,.${containerClass} button,.${containerClass} input[type=text]`; + const focussableElements = `.${containerClass} a,.${containerClass} button,.${containerClass} input[type=text],.${containerClass} textarea`; return document.querySelectorAll<HTMLElement>(focussableElements); } diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/Toggler-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/Toggler-test.tsx index 3b476d48c72..b21c0d013f4 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/Toggler-test.tsx +++ b/server/sonar-web/src/main/js/components/controls/__tests__/Toggler-test.tsx @@ -36,6 +36,8 @@ const ui = { outButton: byRole('button', { name: 'out' }), overlayButton: byRole('button', { name: 'overlay' }), nextOverlayButton: byRole('button', { name: 'next overlay' }), + overlayTextarea: byRole('textbox'), + overlayLatButton: byRole('button', { name: 'last' }), }; async function openToggler(user: UserEvent) { @@ -55,25 +57,40 @@ function focusOut() { it('should handle key up/down', async () => { const user = userEvent.setup({ delay: null }); - const rerender = renderToggler(); + const rerender = renderToggler( + {}, + <> + <textarea name="test-area" /> + <button type="button">last</button> + </> + ); await openToggler(user); await user.keyboard('{ArrowUp}'); - expect(ui.nextOverlayButton.get()).toHaveFocus(); + expect(ui.overlayLatButton.get()).toHaveFocus(); - await user.keyboard('{ArrowDown}'); - expect(ui.overlayButton.get()).toHaveFocus(); + await user.keyboard('{ArrowUp}'); + expect(ui.overlayTextarea.get()).toHaveFocus(); + // Focus does not escape multiline input await user.keyboard('{ArrowDown}'); - expect(ui.nextOverlayButton.get()).toHaveFocus(); - + expect(ui.overlayTextarea.get()).toHaveFocus(); await user.keyboard('{ArrowUp}'); - expect(ui.overlayButton.get()).toHaveFocus(); + expect(ui.overlayTextarea.get()).toHaveFocus(); + + // Escapt textarea + await user.keyboard('{Tab}'); // No focus change when using shortcut await user.keyboard('{Control>}{ArrowUp}{/Control}'); + expect(ui.overlayLatButton.get()).toHaveFocus(); + + await user.keyboard('{ArrowDown}'); expect(ui.overlayButton.get()).toHaveFocus(); + await user.keyboard('{ArrowDown}'); + expect(ui.nextOverlayButton.get()).toHaveFocus(); + rerender(); await openToggler(user); await user.keyboard('{ArrowDown}'); @@ -202,7 +219,7 @@ it('should open/close correctly when default props is applied', async () => { expect(ui.overlayButton.query()).not.toBeInTheDocument(); }); -function renderToggler(override?: Partial<Toggler['props']>) { +function renderToggler(override?: Partial<Toggler['props']>, additionalOverlay?: React.ReactNode) { function App(props: Partial<Toggler['props']>) { const [open, setOpen] = React.useState(false); @@ -215,6 +232,7 @@ function renderToggler(override?: Partial<Toggler['props']>) { <div className="popup"> <button type="button">overlay</button> <button type="button">next overlay</button> + {additionalOverlay} </div> } {...props} diff --git a/server/sonar-web/src/main/js/helpers/keyboardEventHelpers.ts b/server/sonar-web/src/main/js/helpers/keyboardEventHelpers.ts index fc156ad6da7..39b91dc4bc6 100644 --- a/server/sonar-web/src/main/js/helpers/keyboardEventHelpers.ts +++ b/server/sonar-web/src/main/js/helpers/keyboardEventHelpers.ts @@ -21,6 +21,10 @@ export function isShortcut(event: KeyboardEvent): boolean { return event.ctrlKey || event.metaKey; } +export function isTextarea(event: KeyboardEvent): boolean { + const { tagName } = event.target as HTMLElement; + return ['TEXTAREA'].includes(tagName); +} export function isInput(event: KeyboardEvent): boolean { const { tagName } = event.target as HTMLElement; |