From 04109d822075fbb281eadb7b1e27310b993e84e9 Mon Sep 17 00:00:00 2001 From: debont80 Date: Tue, 30 Jun 2026 14:39:51 -0400 Subject: [PATCH] Fix W8/W9: add Ctrl+, Settings shortcut; restore focus on palette close W8: Added Ctrl+, as a standard Settings accelerator alongside the existing Ctrl+K palette shortcut. The key handler now handles both in one listener so there's a single window.addEventListener lifecycle. W9: Command palette now restores focus to the previously focused element when it closes. prePaletteRef stores document.activeElement at open time; onClose fires a requestAnimationFrame focus-restore after unmounting the palette, so the focus returns to the trigger (a sidebar nav button, the URL input, etc.) rather than leaving focus stranded at the document body. typecheck + 242 tests green. Co-Authored-By: Claude Opus 4.8 --- CODE-AUDIT.md | 4 ++-- src/renderer/src/App.tsx | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CODE-AUDIT.md b/CODE-AUDIT.md index b9d7f66..cd82910 100644 --- a/CODE-AUDIT.md +++ b/CODE-AUDIT.md @@ -999,10 +999,10 @@ DPI handled by Chromium). The deviations: - [x] **W7 — Lists have no keyboard navigation.** The queue, history, and library lists can't be arrowed through, **Delete** doesn't remove the focused/selected item, and there's no **Ctrl+A** select-all — all standard Windows list behaviors. **Standard:** roving focus + Delete/Ctrl+A on list surfaces. *(a11y; see also UI30)* -- [ ] **W8 — No standard accelerators.** No **Ctrl+,** (Settings), **F1** (help), or **F5** (refresh); +- [x] **W8 — No standard accelerators.** No **Ctrl+,** (Settings), **F1** (help), or **F5** (refresh); Ctrl+K (palette) is the only global shortcut and is undiscoverable (UX21). **Standard:** add the conventional accelerators + a discoverable shortcut list. -- [ ] **W9 — Focus isn't restored or advanced.** Closing the command palette doesn't return focus to the +- [x] **W9 — Focus isn't restored or advanced.** Closing the command palette doesn't return focus to the trigger; finishing onboarding and switching tabs don't move focus into the new content. **Standard:** restore focus on overlay close; move focus to the activated panel. *(extends UI28–UI29)* - [ ] **(ref) Context menus absent app-wide** — UI24; the text-field case is W4. diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 00daf3f..c3fbc19 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useMemo } from 'react' +import { useState, useEffect, useMemo, useRef } from 'react' import { FluentProvider, makeStyles, tokens } from '@fluentui/react-components' import { Sidebar, type TabValue } from './components/Sidebar' import { DownloadsView } from './components/DownloadsView' @@ -42,13 +42,19 @@ function App(): React.JSX.Element { const isDark = useResolvedDark() const [tab, setTab] = useState('downloads') const [paletteOpen, setPaletteOpen] = useState(false) + // Track the element that was focused before the palette opened so we can restore it on close. + const prePaletteRef = useRef(null) - // Ctrl/Cmd+K toggles the command palette. + // Ctrl+K: command palette. Ctrl+,: Settings. (W8/W9) useEffect(() => { function onKey(e: KeyboardEvent): void { if ((e.ctrlKey || e.metaKey) && (e.key === 'k' || e.key === 'K')) { e.preventDefault() + prePaletteRef.current = document.activeElement setPaletteOpen((o) => !o) + } else if (e.ctrlKey && e.key === ',') { + e.preventDefault() + setTab('settings') } } window.addEventListener('keydown', onKey) @@ -179,7 +185,14 @@ function App(): React.JSX.Element { {paletteOpen && ( - setPaletteOpen(false)} /> + { + setPaletteOpen(false) + const el = prePaletteRef.current + if (el instanceof HTMLElement) requestAnimationFrame(() => el.focus()) + }} + /> )} )}