diff --git a/designer/client/cypress/e2e/nodeWindow.cy.ts b/designer/client/cypress/e2e/nodeWindow.cy.ts index d8b0486be62..61fd4ec11f9 100644 --- a/designer/client/cypress/e2e/nodeWindow.cy.ts +++ b/designer/client/cypress/e2e/nodeWindow.cy.ts @@ -165,4 +165,15 @@ describe("Node window", () => { .click(); cy.get("[data-testid=window]").its("length").should("eq", 0); }); + + it("should remove input focus and close the window on double escape click", () => { + cy.intercept("POST", "/api/nodes/*/validation").as("inputValidation"); + cy.visitNewProcess(NAME, "testProcess"); + cy.getNode("enricher").dblclick(); + cy.wait("@inputValidation"); + cy.get("[data-testid=window]").should("be.visible"); + cy.get("body").type("{esc}"); + cy.get("body").type("{esc}"); + cy.get("[data-testid=window]").should("not.exist"); + }); }); diff --git a/designer/client/src/components/FormElements.tsx b/designer/client/src/components/FormElements.tsx index 1c5a2a170fa..fdb1a6e9c63 100644 --- a/designer/client/src/components/FormElements.tsx +++ b/designer/client/src/components/FormElements.tsx @@ -32,5 +32,3 @@ export function Button({ className, onClick, ...props }: ButtonProps): JSX.Eleme /> ); } - -export const SelectNode = styled("select")(nodeInputCss); diff --git a/designer/client/src/components/graph/node-modal/tests/TestResultsSelect.tsx b/designer/client/src/components/graph/node-modal/tests/TestResultsSelect.tsx index 9dc8524b80c..7e101237b90 100644 --- a/designer/client/src/components/graph/node-modal/tests/TestResultsSelect.tsx +++ b/designer/client/src/components/graph/node-modal/tests/TestResultsSelect.tsx @@ -1,8 +1,7 @@ import React from "react"; import TestResultUtils, { NodeTestResults, StateForSelectTestResults } from "../../../../common/TestResultUtils"; -import { SelectNode } from "../../../FormElements"; import { css, cx } from "@emotion/css"; -import { Box, FormControl, FormLabel, useTheme } from "@mui/material"; +import { FormControl, FormLabel, useTheme } from "@mui/material"; import { Option, TypeSelect } from "../fragment-input-definition/TypeSelect"; export interface TestResultsSelectProps { diff --git a/designer/client/src/windowManager/useWindows.ts b/designer/client/src/windowManager/useWindows.ts index e7b96cc972b..7916fa3de1f 100644 --- a/designer/client/src/windowManager/useWindows.ts +++ b/designer/client/src/windowManager/useWindows.ts @@ -1,6 +1,6 @@ import { useWindowManager, WindowId, WindowType } from "@touk/window-manager"; import { defaults } from "lodash"; -import { useCallback, useMemo } from "react"; +import { useCallback, useEffect, useMemo } from "react"; import { useUserSettings } from "../common/userSettings"; import { ConfirmDialogData } from "../components/modals/GenericConfirmDialog"; import { InfoDialogData } from "../components/modals/GenericInfoDialog"; @@ -28,8 +28,33 @@ function mapModeToKind(mode: NodeViewMode): WindowKind { return WindowKind.editNode; } +const useRemoveFocusOnEscKey = (isWindowOpen: boolean) => { + useEffect(() => { + if (!isWindowOpen) { + return; + } + + const handleKeyDown = (event: KeyboardEvent) => { + const activeElement = document.activeElement as HTMLElement; + const tagName = activeElement.tagName.toLowerCase(); + const allowedTagNames = ["input", "textarea", "select"]; + + if (event.key === "Escape" && allowedTagNames.includes(tagName)) { + activeElement.blur(); // Removes focus from the current active element + } + }; + + document.addEventListener("keydown", handleKeyDown); + + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, [isWindowOpen]); +}; + export function useWindows(parent?: WindowId) { - const { open: _open, closeAll } = useWindowManager(parent); + const { open: _open, closeAll, windows } = useWindowManager(parent); + useRemoveFocusOnEscKey(windows.length > 0); const [settings] = useUserSettings(); const forceDisableModals = useMemo(() => settings["debug.forceDisableModals"], [settings]);