diff --git a/app/pages/search.vue b/app/pages/search.vue index e01985bfe..2faf3f3be 100644 --- a/app/pages/search.vue +++ b/app/pages/search.vue @@ -541,7 +541,59 @@ function focusElement(el: HTMLElement) { el.scrollIntoView({ block: 'nearest', behavior: 'smooth' }) } +// Navigate to package page +async function navigateToPackage(packageName: string) { + await navigateTo({ + name: 'package', + params: { package: packageName.split('/') }, + }) +} + +// Track the input value when user pressed Enter (for navigating when results arrive) +const pendingEnterQuery = shallowRef(null) + +// Watch for results to navigate when Enter was pressed before results arrived +watch(displayResults, results => { + if (!pendingEnterQuery.value) return + + // Check if input is still focused (user hasn't started navigating or clicked elsewhere) + if (document.activeElement?.tagName !== 'INPUT') { + pendingEnterQuery.value = null + return + } + + // Navigate if first result matches the query that was entered + const firstResult = results[0] + // eslint-disable-next-line no-console + console.log('[search] watcher fired', { + pending: pendingEnterQuery.value, + firstResult: firstResult?.package.name, + }) + if (firstResult?.package.name === pendingEnterQuery.value) { + pendingEnterQuery.value = null + navigateToPackage(firstResult.package.name) + } +}) + function handleResultsKeydown(e: KeyboardEvent) { + // If the active element is an input, navigate to exact match or wait for results + if (e.key === 'Enter' && document.activeElement?.tagName === 'INPUT') { + // Get value directly from input (not from route query, which may be debounced) + const inputValue = (document.activeElement as HTMLInputElement).value.trim() + if (!inputValue) return + + // Check if first result matches the input value exactly + const firstResult = displayResults.value[0] + if (firstResult?.package.name === inputValue) { + pendingEnterQuery.value = null + return navigateToPackage(firstResult.package.name) + } + + // No match yet - store input value, watcher will handle navigation when results arrive + pendingEnterQuery.value = inputValue + return + } + if (totalSelectableCount.value <= 0) return const elements = getFocusableElements()