fix: detect typing inside the QuotedHtml shadow island via composedPath #654

This commit is contained in:
Linus Rath
2026-07-21 23:26:51 +02:00
parent 4ad9267a2d
commit a909593dda
6 changed files with 120 additions and 37 deletions
+5 -14
View File
@@ -2,6 +2,7 @@
import { useEffect, useCallback, useRef } from "react";
import { Email } from "@/lib/jmap/types";
import { isEditableEventTarget } from "@/lib/keyboard";
export interface KeyboardShortcutHandlers {
// Navigation
@@ -43,18 +44,6 @@ export interface UseKeyboardShortcutsOptions {
handlers: KeyboardShortcutHandlers;
}
// Check if user is typing in an input field
function isInputFocused(): boolean {
const activeElement = document.activeElement;
if (!activeElement) return false;
const tagName = activeElement.tagName.toLowerCase();
const isInput = tagName === "input" || tagName === "textarea" || tagName === "select";
const isContentEditable = activeElement.getAttribute("contenteditable") === "true";
return isInput || isContentEditable;
}
// Shortcuts must fire regardless of the active keyboard layout (e.g. Cyrillic,
// Greek). Derive the key from the PHYSICAL key (event.code) instead of the
// layout-dependent event.key: letters from KeyA..KeyZ, and the symbol shortcuts
@@ -94,8 +83,10 @@ export function useKeyboardShortcuts({
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
// Don't trigger shortcuts when typing in inputs
if (isInputFocused()) return;
// Don't trigger shortcuts when typing in inputs. Must be event-based
// (composedPath), not document.activeElement: the QuotedHtml island's
// shadow root retargets activeElement to its plain-div host (#654).
if (isEditableEventTarget(event)) return;
const h = handlersRef.current;
const key = physicalShortcutKey(event);