1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-21 18:55:36 +02:00

feat(frontend): focus search input on ⌘K/Ctrl+K

Add a global keydown handler that focuses (and selects) the search
input when Meta+K or Ctrl+K is pressed. If the current view is not
'archive', switch to it first and focus the input after the next
render frame via a pendingSearchFocus ref + requestAnimationFrame.

The ⌘K hint badge in the toolbar was already present; this wires
the behaviour behind it.
This commit is contained in:
TheGeneralist 2026-07-13 14:28:22 +02:00
parent 72cf7ff642
commit 4ca1dd7872
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4

View file

@ -102,6 +102,8 @@ export default function App() {
// Entry detail (shared between PreviewPanel and ContextRail)
const [entryDetail, setEntryDetail] = useState(null)
const detailSeqRef = useRef(0)
const searchInputRef = useRef(null)
const pendingSearchFocus = useRef(false)
const humanizeTags = currentUser?.humanize_slugs ?? false;
@ -266,6 +268,34 @@ export default function App() {
setSelectedEntryUid(prev => prev === entryUid ? null : prev)
}, [])
// K / Ctrl+K: focus the search input, switching to archive view first if needed.
useEffect(() => {
const handler = (e) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault()
if (view === 'archive') {
searchInputRef.current?.focus()
searchInputRef.current?.select()
} else {
pendingSearchFocus.current = true
setView('archive')
}
}
}
document.addEventListener('keydown', handler)
return () => document.removeEventListener('keydown', handler)
}, [view])
// After switching to archive view via K, focus the search input once rendered.
useEffect(() => {
if (view === 'archive' && pendingSearchFocus.current) {
pendingSearchFocus.current = false
requestAnimationFrame(() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
})
}
}, [view])
const handleCaptureClick = useCallback(() => {
setCaptureDialogOpen(true)
}, [])
@ -349,6 +379,7 @@ export default function App() {
</svg>
</span>
<input
ref={searchInputRef}
className="search-input"
type="search"
aria-label="Search archive"