From f7e7dfd161742836bede0806b759283c49778a9d Mon Sep 17 00:00:00 2001 From: mkelvers Date: Sat, 6 Jun 2026 16:54:03 +0200 Subject: [PATCH] feat: improve command palette focus management and aria --- static/search.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/static/search.ts b/static/search.ts index 6f038b8..38de6ac 100644 --- a/static/search.ts +++ b/static/search.ts @@ -29,6 +29,7 @@ let lastQuery = ""; let continueExpanded = false; let activeRequestController: AbortController | undefined; const responseCache = new Map(); +let lastFocusedPaletteOpener: HTMLElement | null = null; const iconPaths: Record = { bookmark: "M19 21l-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z", @@ -62,6 +63,13 @@ const isTypingTarget = (target: EventTarget | null): boolean => const isOpen = (): boolean => paletteDialog?.classList.contains("flex") ?? false; +const setDialogState = (open: boolean): void => { + if (!paletteDialog) return; + paletteDialog.classList.toggle("hidden", !open); + paletteDialog.classList.toggle("flex", open); + paletteDialog.setAttribute("aria-hidden", open ? "false" : "true"); +}; + const setShortcutHints = (): void => { shortcutHints.forEach((hint) => { hint.textContent = isMac() ? "⌘P" : "Ctrl P"; @@ -391,9 +399,9 @@ const openPalette = (): void => { return; } - paletteDialog.classList.remove("hidden"); - paletteDialog.classList.add("flex"); - paletteDialog.setAttribute("aria-hidden", "false"); + lastFocusedPaletteOpener = + document.activeElement instanceof HTMLElement ? document.activeElement : null; + setDialogState(true); paletteInput.value = ""; paletteInput.focus(); continueExpanded = false; @@ -405,9 +413,7 @@ const closePalette = (): void => { return; } - paletteDialog.classList.add("hidden"); - paletteDialog.classList.remove("flex"); - paletteDialog.setAttribute("aria-hidden", "true"); + setDialogState(false); if (activeRequestController) { activeRequestController.abort(); activeRequestController = undefined; @@ -417,6 +423,7 @@ const closePalette = (): void => { paletteItems = []; continueExpanded = false; clearResults(); + lastFocusedPaletteOpener?.focus(); }; const onDocumentClick = (event: MouseEvent): void => { @@ -490,6 +497,9 @@ const initCommandPalette = (): void => { paletteInput.addEventListener("keydown", onInputKeydown); document.addEventListener("click", onDocumentClick); document.addEventListener("keydown", onDocumentKeydown); + paletteDialog?.setAttribute("aria-hidden", "true"); + closestFocusable(paletteRoot ?? document.body); }; initCommandPalette(); +import { closestFocusable } from "./utils";