mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-02-18 13:29:36 +01:00
feat: close dropdown on escape (#7750)
This commit is contained in:
parent
a07f6e9e3a
commit
a38e82f999
@ -0,0 +1,20 @@
|
|||||||
|
import { Excalidraw } from "../../index";
|
||||||
|
import { KEYS } from "../../keys";
|
||||||
|
import { Keyboard } from "../../tests/helpers/ui";
|
||||||
|
import { render, waitFor, getByTestId } from "../../tests/test-utils";
|
||||||
|
|
||||||
|
describe("Test <DropdownMenu/>", () => {
|
||||||
|
it("should", async () => {
|
||||||
|
const { container } = await render(<Excalidraw />);
|
||||||
|
|
||||||
|
expect(window.h.state.openMenu).toBe(null);
|
||||||
|
|
||||||
|
getByTestId(container, "main-menu-trigger").click();
|
||||||
|
expect(window.h.state.openMenu).toBe("canvas");
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
Keyboard.keyDown(KEYS.ESCAPE);
|
||||||
|
expect(window.h.state.openMenu).toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -2,9 +2,12 @@ import { Island } from "../Island";
|
|||||||
import { useDevice } from "../App";
|
import { useDevice } from "../App";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import Stack from "../Stack";
|
import Stack from "../Stack";
|
||||||
import React, { useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import { DropdownMenuContentPropsContext } from "./common";
|
import { DropdownMenuContentPropsContext } from "./common";
|
||||||
import { useOutsideClick } from "../../hooks/useOutsideClick";
|
import { useOutsideClick } from "../../hooks/useOutsideClick";
|
||||||
|
import { KEYS } from "../../keys";
|
||||||
|
import { EVENT } from "../../constants";
|
||||||
|
import { useStable } from "../../hooks/useStable";
|
||||||
|
|
||||||
const MenuContent = ({
|
const MenuContent = ({
|
||||||
children,
|
children,
|
||||||
@ -25,10 +28,30 @@ const MenuContent = ({
|
|||||||
const device = useDevice();
|
const device = useDevice();
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const callbacksRef = useStable({ onClickOutside });
|
||||||
|
|
||||||
useOutsideClick(menuRef, () => {
|
useOutsideClick(menuRef, () => {
|
||||||
onClickOutside?.();
|
callbacksRef.onClickOutside?.();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onKeyDown = (event: KeyboardEvent) => {
|
||||||
|
if (event.key === KEYS.ESCAPE) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
callbacksRef.onClickOutside?.();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener(EVENT.KEYDOWN, onKeyDown, {
|
||||||
|
// so that we can stop propagation of the event before it reaches
|
||||||
|
// event handlers that were bound before this one
|
||||||
|
capture: true,
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener(EVENT.KEYDOWN, onKeyDown);
|
||||||
|
};
|
||||||
|
}, [callbacksRef]);
|
||||||
|
|
||||||
const classNames = clsx(`dropdown-menu ${className}`, {
|
const classNames = clsx(`dropdown-menu ${className}`, {
|
||||||
"dropdown-menu--mobile": device.editor.isMobile,
|
"dropdown-menu--mobile": device.editor.isMobile,
|
||||||
}).trim();
|
}).trim();
|
||||||
|
Loading…
Reference in New Issue
Block a user