escape closes context menus

This commit is contained in:
Michael Peters 2021-12-30 20:40:45 -06:00
parent 59f4829fa9
commit 640b671568
3 changed files with 18 additions and 4 deletions

View File

@ -15,7 +15,7 @@ const Overlay: FC<OverlayProps> = (props: OverlayProps) => {
const { childRootRef, close, children } = props; const { childRootRef, close, children } = props;
if (childRootRef) { if (childRootRef) {
ReactHelper.useCloseWhenClickedOrContextOutsideEffect(childRootRef, close); ReactHelper.useCloseWhenEscapeOrClickedOrContextOutsideEffect(childRootRef, close);
} }
const keyDownHandler = useCallback((e: KeyboardEvent) => { const keyDownHandler = useCallback((e: KeyboardEvent) => {

View File

@ -17,7 +17,7 @@ const ContextMenu: FC<ContextMenuProps> = (props: ContextMenuProps) => {
const rootRef = useRef<HTMLDivElement>(null); const rootRef = useRef<HTMLDivElement>(null);
ReactHelper.useCloseWhenClickedOrContextOutsideEffect(rootRef, close); ReactHelper.useCloseWhenEscapeOrClickedOrContextOutsideEffect(rootRef, close);
return ( return (
<Context rootRef={rootRef} relativeToRef={relativeToRef} relativeToPos={relativeToPos} alignment={alignment}> <Context rootRef={rootRef} relativeToRef={relativeToRef} relativeToPos={relativeToPos} alignment={alignment}>

View File

@ -342,7 +342,7 @@ export default class ReactHelper {
} }
// Makes sure to also allow you to fly-out a click starting inside of the ref'd element but was dragged outside // Makes sure to also allow you to fly-out a click starting inside of the ref'd element but was dragged outside
static useCloseWhenClickedOrContextOutsideEffect(ref: RefObject<HTMLElement>, close: () => void) { static useCloseWhenEscapeOrClickedOrContextOutsideEffect(ref: RefObject<HTMLElement>, close: () => void) {
// Have to use a ref here and not states since we can't re-assign state between mouseup and click // Have to use a ref here and not states since we can't re-assign state between mouseup and click
const mouseRef = useRef<{ mouseDownTarget: Node | null, mouseUpTarget: Node | null}>({ mouseDownTarget: null, mouseUpTarget: null }); const mouseRef = useRef<{ mouseDownTarget: Node | null, mouseUpTarget: Node | null}>({ mouseDownTarget: null, mouseUpTarget: null });
@ -384,7 +384,14 @@ export default class ReactHelper {
if (ref.current.contains(event.target as Node)) return; if (ref.current.contains(event.target as Node)) return;
// Context menu is fired on mouse-down so no need to do special checks. // Context menu is fired on mouse-down so no need to do special checks.
close(); close();
}, [ ref ]) }, [ ref ]);
const handleKeyDown = useCallback((event: KeyboardEvent) => {
if (!ref.current) return;
if (event.key !== 'Escape') return;
close();
}, [ ref ]);
useEffect(() => { useEffect(() => {
document.addEventListener('click', handleClickOutside); document.addEventListener('click', handleClickOutside);
@ -413,6 +420,13 @@ export default class ReactHelper {
document.removeEventListener('contextmenu', handleContextMenu); document.removeEventListener('contextmenu', handleContextMenu);
} }
}, [ handleClickOutside ]); }, [ handleClickOutside ]);
useEffect(() => {
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
}
}, [ handleKeyDown ]);
} }
static useAlignment( static useAlignment(