From 3066b38c5e33dcd6bb13e38084be880be32a026e Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Wed, 3 Feb 2021 17:01:29 +0100 Subject: [PATCH] Grafana-ui: fixes closing modals with escape key (#30745) * feat(grafana-ui): add an escape key listener to Modal * Update packages/grafana-ui/src/components/Modal/Modal.tsx Co-authored-by: Alex Khomenko * feat(grafana-ui): add closeOnEscape prop to control Modal behaviour Co-authored-by: Alex Khomenko --- .../grafana-ui/src/components/Modal/Modal.tsx | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/grafana-ui/src/components/Modal/Modal.tsx b/packages/grafana-ui/src/components/Modal/Modal.tsx index 777a764b105..e90a9202357 100644 --- a/packages/grafana-ui/src/components/Modal/Modal.tsx +++ b/packages/grafana-ui/src/components/Modal/Modal.tsx @@ -1,4 +1,4 @@ -import React, { FC, PropsWithChildren, useCallback } from 'react'; +import React, { FC, PropsWithChildren, useCallback, useEffect } from 'react'; import { Portal } from '../Portal/Portal'; import { cx } from 'emotion'; import { useTheme } from '../../themes'; @@ -14,6 +14,7 @@ export interface Props { title: string | JSX.Element; className?: string; contentClassName?: string; + closeOnEscape?: boolean; isOpen?: boolean; onDismiss?: () => void; @@ -27,6 +28,7 @@ export function Modal(props: PropsWithChildren): ReturnType> { title, children, isOpen = false, + closeOnEscape = true, className, contentClassName, onDismiss: propsOnDismiss, @@ -40,6 +42,23 @@ export function Modal(props: PropsWithChildren): ReturnType> { } }, [propsOnDismiss]); + const onEscKey = (ev: KeyboardEvent) => { + if (ev.key === 'Esc' || ev.key === 'Escape') { + onDismiss(); + } + }; + + useEffect(() => { + if (isOpen && closeOnEscape) { + document.addEventListener('keydown', onEscKey, false); + } else { + document.removeEventListener('keydown', onEscKey, false); + } + return () => { + document.removeEventListener('keydown', onEscKey, false); + }; + }, [closeOnEscape, isOpen]); + if (!isOpen) { return null; }