Skip to content

Commit f4c6488

Browse files
kalu5danielroe
andauthored
feat: enter key open the first package when searching (#993)
Co-authored-by: Daniel Roe <daniel@roe.dev>
1 parent 65cfef0 commit f4c6488

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

app/pages/search.vue

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,59 @@ function focusElement(el: HTMLElement) {
541541
el.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
542542
}
543543
544+
// Navigate to package page
545+
async function navigateToPackage(packageName: string) {
546+
await navigateTo({
547+
name: 'package',
548+
params: { package: packageName.split('/') },
549+
})
550+
}
551+
552+
// Track the input value when user pressed Enter (for navigating when results arrive)
553+
const pendingEnterQuery = shallowRef<string | null>(null)
554+
555+
// Watch for results to navigate when Enter was pressed before results arrived
556+
watch(displayResults, results => {
557+
if (!pendingEnterQuery.value) return
558+
559+
// Check if input is still focused (user hasn't started navigating or clicked elsewhere)
560+
if (document.activeElement?.tagName !== 'INPUT') {
561+
pendingEnterQuery.value = null
562+
return
563+
}
564+
565+
// Navigate if first result matches the query that was entered
566+
const firstResult = results[0]
567+
// eslint-disable-next-line no-console
568+
console.log('[search] watcher fired', {
569+
pending: pendingEnterQuery.value,
570+
firstResult: firstResult?.package.name,
571+
})
572+
if (firstResult?.package.name === pendingEnterQuery.value) {
573+
pendingEnterQuery.value = null
574+
navigateToPackage(firstResult.package.name)
575+
}
576+
})
577+
544578
function handleResultsKeydown(e: KeyboardEvent) {
579+
// If the active element is an input, navigate to exact match or wait for results
580+
if (e.key === 'Enter' && document.activeElement?.tagName === 'INPUT') {
581+
// Get value directly from input (not from route query, which may be debounced)
582+
const inputValue = (document.activeElement as HTMLInputElement).value.trim()
583+
if (!inputValue) return
584+
585+
// Check if first result matches the input value exactly
586+
const firstResult = displayResults.value[0]
587+
if (firstResult?.package.name === inputValue) {
588+
pendingEnterQuery.value = null
589+
return navigateToPackage(firstResult.package.name)
590+
}
591+
592+
// No match yet - store input value, watcher will handle navigation when results arrive
593+
pendingEnterQuery.value = inputValue
594+
return
595+
}
596+
545597
if (totalSelectableCount.value <= 0) return
546598
547599
const elements = getFocusableElements()

0 commit comments

Comments
 (0)