diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx
new file mode 100644
index 0000000000..3aae1d0c7e
--- /dev/null
+++ b/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx
@@ -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 ", () => {
+ it("should", async () => {
+ const { container } = await render();
+
+ 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);
+ });
+ });
+});
diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx
index e266cecf41..374e5c05d3 100644
--- a/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx
+++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx
@@ -2,9 +2,12 @@ import { Island } from "../Island";
import { useDevice } from "../App";
import clsx from "clsx";
import Stack from "../Stack";
-import React, { useRef } from "react";
+import React, { useEffect, useRef } from "react";
import { DropdownMenuContentPropsContext } from "./common";
import { useOutsideClick } from "../../hooks/useOutsideClick";
+import { KEYS } from "../../keys";
+import { EVENT } from "../../constants";
+import { useStable } from "../../hooks/useStable";
const MenuContent = ({
children,
@@ -25,10 +28,30 @@ const MenuContent = ({
const device = useDevice();
const menuRef = useRef(null);
+ const callbacksRef = useStable({ onClickOutside });
+
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}`, {
"dropdown-menu--mobile": device.editor.isMobile,
}).trim();