From bf3e135679ab7d61b2076c34603cd7948a5bba97 Mon Sep 17 00:00:00 2001 From: Sharad Saha <76741905+SharadSaha@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:23:41 +0530 Subject: [PATCH] fix: avoid shortcut conflicts in CodeMirror editors (#5224) Prevents `alt+up` and `alt+down` from triggering global keybindings when focus is in CodeMirror editors or other typable elements. --- .../src/helpers/keybindings.ts | 11 ++- .../src/helpers/utils/__tests__/dom.spec.js | 77 +++++++++++++++++++ .../src/helpers/utils/dom.ts | 10 +++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 packages/hoppscotch-common/src/helpers/utils/__tests__/dom.spec.js diff --git a/packages/hoppscotch-common/src/helpers/keybindings.ts b/packages/hoppscotch-common/src/helpers/keybindings.ts index b06901aa..9a0528d6 100644 --- a/packages/hoppscotch-common/src/helpers/keybindings.ts +++ b/packages/hoppscotch-common/src/helpers/keybindings.ts @@ -1,7 +1,7 @@ import { onBeforeUnmount, onMounted } from "vue" import { HoppActionWithOptionalArgs, invokeAction } from "./actions" import { isAppleDevice } from "./platformutils" -import { isDOMElement, isTypableElement } from "./utils/dom" +import { isCodeMirrorEditor, isDOMElement, isTypableElement } from "./utils/dom" import { getKernelMode } from "@hoppscotch/kernel" import { listen } from "@tauri-apps/api/event" @@ -193,6 +193,15 @@ function generateKeybindingString(ev: KeyboardEvent): ShortcutKey | null { return null } + // Restrict alt+up and alt+down when the target is a codemirror editor + if ( + modifierKey === "alt" && + (key === "up" || key === "down") && + isCodeMirrorEditor(target) + ) { + return null + } + return `${modifierKey}-${key}` } diff --git a/packages/hoppscotch-common/src/helpers/utils/__tests__/dom.spec.js b/packages/hoppscotch-common/src/helpers/utils/__tests__/dom.spec.js new file mode 100644 index 00000000..8240a642 --- /dev/null +++ b/packages/hoppscotch-common/src/helpers/utils/__tests__/dom.spec.js @@ -0,0 +1,77 @@ +import { describe, expect, test } from "vitest" +import { isDOMElement, isTypableElement, isCodeMirrorEditor } from "../dom" + +describe("isDOMElement", () => { + test("returns true for valid HTMLElement", () => { + const div = document.createElement("div") + expect(isDOMElement(div)).toBe(true) + }) + + test("returns false for non-HTMLElement inputs", () => { + expect(isDOMElement(null)).toBe(false) + expect(isDOMElement(undefined)).toBe(false) + expect(isDOMElement("div")).toBe(false) + expect(isDOMElement(123)).toBe(false) + expect(isDOMElement({})).toBe(false) + }) +}) + +describe("isTypableElement", () => { + test("returns true for enabled ", () => { + const input = document.createElement("input") + expect(isTypableElement(input)).toBe(true) + }) + + test("returns false for disabled ", () => { + const input = document.createElement("input") + input.disabled = true + expect(isTypableElement(input)).toBe(false) + }) + + test("returns true for enabled