[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: enter key open the first package when searching (#993)

Co-authored-by: Daniel Roe <daniel@roe.dev>

authored by

Jialong Lu
Daniel Roe
and committed by
GitHub
f4c64881 65cfef0f

+52
+52
app/pages/search.vue
··· 541 541 el.scrollIntoView({ block: 'nearest', behavior: 'smooth' }) 542 542 } 543 543 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 + 544 578 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 + 545 597 if (totalSelectableCount.value <= 0) return 546 598 547 599 const elements = getFocusableElements()