mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-11-03 20:34:40 +01:00 
			
		
		
		
	feat: close dropdown on escape (#7750)
This commit is contained in:
		@@ -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 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<HTMLDivElement>(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();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user