diff --git a/ui/package-lock.json b/ui/package-lock.json index 910fe58c8..1c6959dea 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -12412,6 +12412,14 @@ "prop-types": "^15.6.0" } }, + "react-hotkeys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-2.0.0.tgz", + "integrity": "sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q==", + "requires": { + "prop-types": "^15.6.1" + } + }, "react-idle-timer": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/react-idle-timer/-/react-idle-timer-4.2.8.tgz", diff --git a/ui/package.json b/ui/package.json index eb65f5b0f..300540214 100644 --- a/ui/package.json +++ b/ui/package.json @@ -34,6 +34,7 @@ "react-datepicker": "2.8.0", "react-dom": "16.8.6", "react-highlighter": "0.4.3", + "react-hotkeys": "2.0.0", "react-idle-timer": "4.2.8", "react-input-range": "1.3.0", "react-js-pagination": "3.0.2", diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/DeleteSilence.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/DeleteSilence.js index ab5ac9143..055dbbc58 100644 --- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/DeleteSilence.js +++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/DeleteSilence.js @@ -281,7 +281,7 @@ const DeleteSilence = observer( Delete - + - + diff --git a/ui/src/Components/Modal/index.js b/ui/src/Components/Modal/index.js index fa3b99253..3fc64b181 100644 --- a/ui/src/Components/Modal/index.js +++ b/ui/src/Components/Modal/index.js @@ -6,6 +6,8 @@ import { observer } from "mobx-react"; import { disableBodyScroll, clearAllBodyScrollLocks } from "body-scroll-lock"; +import { HotKeys } from "react-hotkeys"; + import { MountModal, MountModalBackdrop @@ -16,6 +18,7 @@ const Modal = observer( static propTypes = { size: PropTypes.oneOf(["lg", "xl"]), isOpen: PropTypes.bool.isRequired, + toggleOpen: PropTypes.func.isRequired, children: PropTypes.node.isRequired }; static defaultProps = { @@ -25,11 +28,13 @@ const Modal = observer( constructor(props) { super(props); this.modalRef = React.createRef(); + this.HotKeysRef = React.createRef(); } toggleBodyClass = isOpen => { document.body.classList.toggle("modal-open", isOpen); if (isOpen) { + this.HotKeysRef.current.focus(); disableBodyScroll(this.modalRef.current); } else { clearAllBodyScrollLocks(); @@ -51,10 +56,14 @@ const Modal = observer( } render() { - const { size, isOpen, children, ...props } = this.props; + const { size, isOpen, toggleOpen, children, ...props } = this.props; return ReactDOM.createPortal( - +
@@ -65,7 +74,7 @@ const Modal = observer(
- , + , document.body ); } diff --git a/ui/src/Components/Modal/index.test.js b/ui/src/Components/Modal/index.test.js index bcd9200a3..35e65fcd7 100644 --- a/ui/src/Components/Modal/index.test.js +++ b/ui/src/Components/Modal/index.test.js @@ -4,14 +4,20 @@ import { mount } from "enzyme"; import { Modal } from "."; +const fakeToggle = jest.fn(); + const MountedModal = isOpen => { return mount( - +
); }; +afterEach(() => { + jest.resetAllMocks(); +}); + describe("", () => { it("'modal-open' class is appended to body node when modal is visible", () => { MountedModal(true); @@ -32,11 +38,17 @@ describe("", () => { it("passes extra props down to the MountModal animation component", () => { const onExited = jest.fn(); const tree = mount( - +
); const mountModal = tree.find("MountModal"); expect(mountModal.props().onExited).toBe(onExited); }); + + it("toggleOpen is called after pressing 'esc'", () => { + const tree = MountedModal(true); + tree.simulate("keyDown", { key: "Escape", keyCode: 27, which: 27 }); + expect(fakeToggle).toHaveBeenCalled(); + }); }); diff --git a/ui/src/Components/OverviewModal/index.js b/ui/src/Components/OverviewModal/index.js index 468dc4bff..2263870e2 100644 --- a/ui/src/Components/OverviewModal/index.js +++ b/ui/src/Components/OverviewModal/index.js @@ -58,7 +58,11 @@ const OverviewModal = observer(
- + diff --git a/ui/src/Components/SilenceModal/index.js b/ui/src/Components/SilenceModal/index.js index a4ae46f21..5b81f1cfb 100644 --- a/ui/src/Components/SilenceModal/index.js +++ b/ui/src/Components/SilenceModal/index.js @@ -51,6 +51,7 @@ const SilenceModal = observer(