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 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 14:39:51 -04:00
parent 53aaed5fef
commit 04109d8220
2 changed files with 18 additions and 5 deletions
+16 -3
View File
@@ -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<TabValue>('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<Element | null>(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 {
</main>
{paletteOpen && (
<CommandPalette actions={paletteActions} onClose={() => setPaletteOpen(false)} />
<CommandPalette
actions={paletteActions}
onClose={() => {
setPaletteOpen(false)
const el = prePaletteRef.current
if (el instanceof HTMLElement) requestAnimationFrame(() => el.focus())
}}
/>
)}
</>
)}