diff --git a/src/ui/anchored-panel.svelte b/src/ui/anchored-panel.svelte index ac1f17e..1bef234 100644 --- a/src/ui/anchored-panel.svelte +++ b/src/ui/anchored-panel.svelte @@ -51,6 +51,7 @@ function mount(node: HTMLElement) { panel = node; + const win = node.ownerDocument.defaultView ?? window; measure(); if (autofocus) { (node.querySelector("input") ?? node).focus({ @@ -64,17 +65,27 @@ const reflow = (): void => measure(); document.addEventListener("pointerdown", outside, true); window.addEventListener("resize", reflow); + win.addEventListener("keydown", keys, true); return { destroy() { document.removeEventListener("pointerdown", outside, true); window.removeEventListener("resize", reflow); + win.removeEventListener("keydown", keys, true); panel = null; }, }; } + /** + * Read at the window's capture phase rather than on the panel itself. + * Obsidian's keymap listens there first, and a plugin that claims a key + * through `app.scope` — Tasks claims Tab — stops the event before it ever + * reaches an element handler. A listener on the same node still runs after + * that, so this is the one place the panel's keys cannot be taken away. + */ function keys(event: KeyboardEvent): void { + if (!panel?.contains(event.target as Node)) return; event.stopPropagation(); if (event.key === "Escape" && !event.defaultPrevented) { event.preventDefault(); @@ -91,13 +102,11 @@ -