11<script setup lang="ts">
22const route = useRoute ()
3+ const router = useRouter ()
34
45const isHomepage = computed (() => route .path === ' /' )
56
@@ -8,6 +9,44 @@ useHead({
89 return titleChunk ? titleChunk : ' npmx - Better npm Package Browser'
910 },
1011})
12+
13+ // Global keyboard shortcut: "/" focuses search or navigates to search page
14+ function handleGlobalKeydown(e : KeyboardEvent ) {
15+ // Ignore if user is typing in an input, textarea, or contenteditable
16+ const target = e .target as HTMLElement
17+ if (
18+ target .tagName === ' INPUT'
19+ || target .tagName === ' TEXTAREA'
20+ || target .isContentEditable
21+ ) {
22+ return
23+ }
24+
25+ if (e .key === ' /' ) {
26+ e .preventDefault ()
27+
28+ // Try to find and focus search input on current page
29+ const searchInput = document .querySelector <HTMLInputElement >(
30+ ' input[type="search"], input[name="q"]' ,
31+ )
32+
33+ if (searchInput ) {
34+ searchInput .focus ()
35+ }
36+ else {
37+ // Navigate to search page
38+ router .push (' /search' )
39+ }
40+ }
41+ }
42+
43+ onMounted (() => {
44+ document .addEventListener (' keydown' , handleGlobalKeydown )
45+ })
46+
47+ onUnmounted (() => {
48+ document .removeEventListener (' keydown' , handleGlobalKeydown )
49+ })
1150 </script >
1251
1352<template >
@@ -40,9 +79,10 @@ useHead({
4079 <li class =" flex" >
4180 <NuxtLink
4281 to =" /search"
43- class =" link-subtle font-mono text-sm inline-flex items-center"
82+ class =" link-subtle font-mono text-sm inline-flex items-center gap-2 "
4483 >
4584 search
85+ <kbd class =" hidden sm:inline-flex items-center justify-center w-5 h-5 text-xs bg-bg-muted border border-border rounded" >/</kbd >
4686 </NuxtLink >
4787 </li >
4888 <li class =" flex" >
0 commit comments