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