From d2a7229f78dd17d1ef6b4dbd9bbe23aa7e84f181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20R=C3=B8mer=20Hesselbjerg?= Date: Fri, 30 Jan 2026 20:53:47 +0100 Subject: [PATCH 1/7] Highlight kbd elements on '?' press --- app/app.vue | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/app/app.vue b/app/app.vue index 2e9d67ea24..f43d936484 100644 --- a/app/app.vue +++ b/app/app.vue @@ -59,6 +59,20 @@ function handleGlobalKeydown(e: KeyboardEvent) { router.push('/search') } + + if (e.key === '?') { + e.preventDefault() + const kbdElements = document.querySelectorAll('kbd') + for (const kbd of kbdElements) { + kbd.classList.remove('kbd-highlight') + kbd.classList.add('kbd-highlight') + } + setTimeout(() => { + for (const kbd of kbdElements) { + kbd.classList.remove('kbd-highlight') + } + }, 700) + } } if (import.meta.client) { @@ -81,3 +95,24 @@ if (import.meta.client) { + + From b79e7f8eada8a2ea7f5807f4d81ffab1bd5b9b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20R=C3=B8mer=20Hesselbjerg?= Date: Fri, 30 Jan 2026 21:52:04 +0100 Subject: [PATCH 2/7] Make animation restart/cancel work properly --- app/app.vue | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/app/app.vue b/app/app.vue index f43d936484..dde00b3073 100644 --- a/app/app.vue +++ b/app/app.vue @@ -33,6 +33,8 @@ if (import.meta.server) { setJsonLd(createWebSiteSchema()) } +let kbdAnimations: Animation[] = [] + // Global keyboard shortcut: "/" focuses search or navigates to search page function handleGlobalKeydown(e: KeyboardEvent) { const target = e.target as HTMLElement @@ -62,16 +64,25 @@ function handleGlobalKeydown(e: KeyboardEvent) { if (e.key === '?') { e.preventDefault() + + for (const anim of kbdAnimations) { + anim.cancel() + } + kbdAnimations = [] + const kbdElements = document.querySelectorAll('kbd') for (const kbd of kbdElements) { - kbd.classList.remove('kbd-highlight') - kbd.classList.add('kbd-highlight') + const anim = kbd.animate( + [ + { boxShadow: 'none' }, + { boxShadow: '0 0 4px 2px var(--accent)', offset: 0.15 }, + { boxShadow: '0 0 4px 2px var(--accent)', offset: 0.6 }, + { boxShadow: 'none' }, + ], + { duration: 700, easing: 'ease-out' }, + ) + kbdAnimations.push(anim) } - setTimeout(() => { - for (const kbd of kbdElements) { - kbd.classList.remove('kbd-highlight') - } - }, 700) } } @@ -95,24 +106,3 @@ if (import.meta.client) { - - From f09e42e3924b08e4a7fe6bd8c7b367b22efad2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20R=C3=B8mer=20Hesselbjerg?= Date: Sat, 31 Jan 2026 09:38:57 +0100 Subject: [PATCH 3/7] Animate keyboard shortcut highlights with data-attribute approach Co-authored-by: Nathan Knowler --- app/app.vue | 54 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/app/app.vue b/app/app.vue index dde00b3073..c2c97719a3 100644 --- a/app/app.vue +++ b/app/app.vue @@ -33,9 +33,9 @@ if (import.meta.server) { setJsonLd(createWebSiteSchema()) } -let kbdAnimations: Animation[] = [] - -// Global keyboard shortcut: "/" focuses search or navigates to search page +// Global keyboard shortcut: +// "/" focuses search or navigates to search page +// "?" highlights all keyboard shortcut elements function handleGlobalKeydown(e: KeyboardEvent) { const target = e.target as HTMLElement @@ -64,30 +64,18 @@ function handleGlobalKeydown(e: KeyboardEvent) { if (e.key === '?') { e.preventDefault() - - for (const anim of kbdAnimations) { - anim.cancel() - } - kbdAnimations = [] - - const kbdElements = document.querySelectorAll('kbd') - for (const kbd of kbdElements) { - const anim = kbd.animate( - [ - { boxShadow: 'none' }, - { boxShadow: '0 0 4px 2px var(--accent)', offset: 0.15 }, - { boxShadow: '0 0 4px 2px var(--accent)', offset: 0.6 }, - { boxShadow: 'none' }, - ], - { duration: 700, easing: 'ease-out' }, - ) - kbdAnimations.push(anim) - } + document.documentElement.setAttribute('data-keyboard-shortcut-highlight', 'true') } } +function handleGlobalKeyup() { + // Don't check for key, "?" requires a combination and keys can be released independently + document.documentElement.removeAttribute('data-keyboard-shortcut-highlight') +} + if (import.meta.client) { useEventListener(document, 'keydown', handleGlobalKeydown) + useEventListener(document, 'keyup', handleGlobalKeyup) } @@ -106,3 +94,25 @@ if (import.meta.client) { + + From 8be5e9baabcdcf2b8dc450365cedc6b85f32271c Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sat, 31 Jan 2026 12:17:43 +0000 Subject: [PATCH 4/7] chore: merge in https://github.com/npmx-dev/npmx.dev/pull/461 --- app/app.vue | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/app/app.vue b/app/app.vue index 57d5064ddc..f2060ae3c0 100644 --- a/app/app.vue +++ b/app/app.vue @@ -10,6 +10,7 @@ const { locale, locales } = useI18n() initPreferencesOnPrehydrate() const isHomepage = computed(() => route.name === 'index') +const showKbdHints = shallowRef(false) const localeMap = locales.value.reduce( (acc, l) => { @@ -21,8 +22,9 @@ const localeMap = locales.value.reduce( useHead({ htmlAttrs: { - lang: () => locale.value, - dir: () => localeMap[locale.value] ?? 'ltr', + 'lang': () => locale.value, + 'dir': () => localeMap[locale.value] ?? 'ltr', + 'data-kbd-hints': () => showKbdHints.value, }, titleTemplate: titleChunk => { return titleChunk ? titleChunk : 'npmx - Better npm Package Browser' @@ -42,9 +44,7 @@ function handleGlobalKeydown(e: KeyboardEvent) { const isEditableTarget = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable - if (isEditableTarget) { - return - } + if (isEditableTarget) return if (e.key === '/') { e.preventDefault() @@ -64,13 +64,12 @@ function handleGlobalKeydown(e: KeyboardEvent) { if (e.key === '?') { e.preventDefault() - document.documentElement.setAttribute('data-keyboard-shortcut-highlight', 'true') + showKbdHints.value = true } } function handleGlobalKeyup() { - // Don't check for key, "?" requires a combination and keys can be released independently - document.documentElement.removeAttribute('data-keyboard-shortcut-highlight') + showKbdHints.value = false } if (import.meta.client) { @@ -97,7 +96,7 @@ if (import.meta.client) { From 03738439561a50c605bdf5147099470eb61f77cb Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sat, 31 Jan 2026 12:19:09 +0000 Subject: [PATCH 5/7] chore: add co-authored Co-Authored-By: Nathan Knowler Co-Authored-By: jellydeck <91427591+jellydeck@users.noreply.github.com> From e17c5524d88f527437eaecd1015e6303701da77f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sat, 31 Jan 2026 12:22:54 +0000 Subject: [PATCH 6/7] chore: add co-authored Co-authored-by: Nathan Knowler Co-authored-by: jellydeck <91427591+jellydeck@users.noreply.github.com> From 5f102e4141d3febfb70eb258755b876ec7eaa769 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sat, 31 Jan 2026 12:24:00 +0000 Subject: [PATCH 7/7] chore: add co-authored Co-Authored-By: jellydeck <91427591+jellydeck@users.noreply.github.com> Co-Authored-By: Nathan Knowler