From 506023b0f3cc7dff21a298ee9573d6426d86d386 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 1 Mar 2020 21:03:38 -0800 Subject: [PATCH] Scrolling and hotkey improvements New: Use Esc/Enter for cancel/accept in confirmation modals Fixed: Modals focused when opened Fixed: Scrolling with keyboard unless focus is shifted out of scrollable area Closes #3291 --- frontend/src/Components/Modal/ConfirmModal.js | 17 +++++-- frontend/src/Components/Modal/Modal.js | 39 ++++++++------- frontend/src/Components/Scroller/Scroller.js | 3 ++ frontend/src/Components/keyboardShortcuts.js | 10 ++++ frontend/src/Settings/PendingChangesModal.js | 16 ++++-- package.json | 1 + yarn.lock | 49 +++++++++++++++++++ 7 files changed, 108 insertions(+), 27 deletions(-) diff --git a/frontend/src/Components/Modal/ConfirmModal.js b/frontend/src/Components/Modal/ConfirmModal.js index 5bb783d43..529a5d973 100644 --- a/frontend/src/Components/Modal/ConfirmModal.js +++ b/frontend/src/Components/Modal/ConfirmModal.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useEffect } from 'react'; import { kinds, sizes } from 'Helpers/Props'; +import keyboardShortcuts from 'Components/keyboardShortcuts'; import Button from 'Components/Link/Button'; import SpinnerButton from 'Components/Link/SpinnerButton'; import Modal from 'Components/Modal/Modal'; @@ -21,9 +22,14 @@ function ConfirmModal(props) { hideCancelButton, isSpinning, onConfirm, - onCancel + onCancel, + bindShortcut } = props; + useEffect(() => { + bindShortcut('enter', onConfirm); + }, [onConfirm]); + return ( +
- - {children} - + + {children} + +
- , +
, this._node ); } diff --git a/frontend/src/Components/Scroller/Scroller.js b/frontend/src/Components/Scroller/Scroller.js index 22fae04c6..4ae94c78b 100644 --- a/frontend/src/Components/Scroller/Scroller.js +++ b/frontend/src/Components/Scroller/Scroller.js @@ -23,6 +23,8 @@ class Scroller extends Component { if (this.props.scrollTop != null) { this._scroller.scrollTop = scrollTop; } + + this._scroller.focus({ preventScroll: true }); } // @@ -58,6 +60,7 @@ class Scroller extends Component { styles[scrollDirection], autoScroll && styles.autoScroll )} + tabIndex={-1} {...otherProps} > {children} diff --git a/frontend/src/Components/keyboardShortcuts.js b/frontend/src/Components/keyboardShortcuts.js index f43139e4a..ab33a378f 100644 --- a/frontend/src/Components/keyboardShortcuts.js +++ b/frontend/src/Components/keyboardShortcuts.js @@ -8,6 +8,16 @@ export const shortcuts = { name: 'Open This Modal' }, + CLOSE_MODAL: { + key: 'Esc', + name: 'Close Current Modal' + }, + + ACCEPT_CONFIRM_MODAL: { + key: 'Enter', + name: 'Accept Confirmation Modal' + }, + SERIES_SEARCH_INPUT: { key: 's', name: 'Focus Search Box' diff --git a/frontend/src/Settings/PendingChangesModal.js b/frontend/src/Settings/PendingChangesModal.js index e3b14e228..b23d86418 100644 --- a/frontend/src/Settings/PendingChangesModal.js +++ b/frontend/src/Settings/PendingChangesModal.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useEffect } from 'react'; import { kinds } from 'Helpers/Props'; +import keyboardShortcuts from 'Components/keyboardShortcuts'; import Button from 'Components/Link/Button'; import Modal from 'Components/Modal/Modal'; import ModalContent from 'Components/Modal/ModalContent'; @@ -12,9 +13,14 @@ function PendingChangesModal(props) { const { isOpen, onConfirm, - onCancel + onCancel, + bindShortcut } = props; + useEffect(() => { + bindShortcut('enter', onConfirm); + }, [onConfirm]); + return (