Skip to content

Commit 0d40d1e

Browse files
authored
refactor: prefer vueuse onKeyStroke (#1039)
1 parent fabe1c2 commit 0d40d1e

File tree

4 files changed

+75
-59
lines changed

4 files changed

+75
-59
lines changed

app/app.vue

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
22
import type { Directions } from '@nuxtjs/i18n'
3-
import { useEventListener } from '@vueuse/core'
3+
import { useEventListener, onKeyDown, onKeyUp } from '@vueuse/core'
44
import { isEditableElement } from '~/utils/input'
55
66
const route = useRoute()
@@ -47,16 +47,12 @@ if (import.meta.server) {
4747
setJsonLd(createWebSiteSchema())
4848
}
4949
50-
// Global keyboard shortcut:
51-
// "/" focuses search or navigates to search page
52-
// "?" highlights all keyboard shortcut elements
53-
function handleGlobalKeydown(e: KeyboardEvent) {
54-
if (isEditableElement(e.target)) return
55-
56-
if (isKeyWithoutModifiers(e, '/')) {
50+
onKeyDown(
51+
'/',
52+
e => {
53+
if (isEditableElement(e.target)) return
5754
e.preventDefault()
5855
59-
// Try to find and focus search input on current page
6056
const searchInput = document.querySelector<HTMLInputElement>(
6157
'input[type="search"], input[name="q"]',
6258
)
@@ -67,18 +63,29 @@ function handleGlobalKeydown(e: KeyboardEvent) {
6763
}
6864
6965
router.push('/search')
70-
}
66+
},
67+
{ dedupe: true },
68+
)
7169
72-
// For "?" we check the key property directly since it's usually combined with shift
73-
if (e.key === '?') {
70+
onKeyDown(
71+
'?',
72+
e => {
73+
if (isEditableElement(e.target)) return
7474
e.preventDefault()
7575
showKbdHints.value = true
76-
}
77-
}
76+
},
77+
{ dedupe: true },
78+
)
7879
79-
function handleGlobalKeyup() {
80-
showKbdHints.value = false
81-
}
80+
onKeyUp(
81+
'?',
82+
e => {
83+
if (isEditableElement(e.target)) return
84+
e.preventDefault()
85+
showKbdHints.value = false
86+
},
87+
{ dedupe: true },
88+
)
8289
8390
// Light dismiss fallback for browsers that don't support closedby="any" (Safari + old Chrome/Firefox)
8491
// https://codepen.io/paramagicdev/pen/gbYompq
@@ -99,9 +106,6 @@ function handleModalLightDismiss(e: MouseEvent) {
99106
}
100107
101108
if (import.meta.client) {
102-
useEventListener(document, 'keydown', handleGlobalKeydown)
103-
useEventListener(document, 'keyup', handleGlobalKeyup)
104-
105109
// Feature check for native light dismiss support via closedby="any"
106110
// https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#closedby
107111
const supportsClosedBy =

app/components/ColumnPicker.vue

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import type { ColumnConfig, ColumnId } from '#shared/types/preferences'
3+
import { onKeyDown } from '@vueuse/core'
34
45
const props = defineProps<{
56
columns: ColumnConfig[]
@@ -26,13 +27,16 @@ onClickOutside(
2627
},
2728
)
2829
29-
// Close on Escape key
30-
useEventListener('keydown', event => {
31-
if (event.key === 'Escape' && isOpen.value) {
30+
onKeyDown(
31+
'Escape',
32+
e => {
33+
if (!isOpen.value) return
3234
isOpen.value = false
3335
buttonRef.value?.focus()
34-
}
35-
})
36+
},
37+
{ dedupe: true },
38+
)
39+
3640
// Columns that can be toggled (name is always visible)
3741
const toggleableColumns = computed(() => props.columns.filter(col => col.id !== 'name'))
3842

app/components/DependencyPathPopup.vue

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<script setup lang="ts">
2+
import { onKeyDown } from '@vueuse/core'
3+
import { UseFocusTrap } from '@vueuse/integrations/useFocusTrap/component'
4+
25
defineProps<{
36
/** Dependency path from root to vulnerable package (readonly from VulnerabilityTreeResult) */
47
path: readonly string[]
@@ -17,13 +20,16 @@ onClickOutside(popupEl, () => {
1720
if (isOpen.value) closePopup()
1821
})
1922
20-
// Close popup on ESC or scroll
21-
function handleKeydown(e: KeyboardEvent) {
22-
if (e.key === 'Escape') closePopup()
23-
}
23+
onKeyDown(
24+
'Escape',
25+
e => {
26+
e.preventDefault()
27+
closePopup()
28+
},
29+
{ dedupe: true, target: popupEl },
30+
)
2431
25-
useEventListener(document, 'keydown', handleKeydown)
26-
useEventListener('scroll', closePopup, true)
32+
useEventListener('scroll', closePopup, { passive: true })
2733
2834
function togglePopup(event: MouseEvent) {
2935
if (isOpen.value) {
@@ -77,34 +83,36 @@ function parsePackageString(pkg: string): { name: string; version: string } {
7783
class="fixed z-[100] bg-bg-elevated border border-border rounded-lg shadow-xl p-3 min-w-64 max-w-sm"
7884
:style="getPopupStyle()"
7985
>
80-
<ul class="list-none m-0 p-0 space-y-0.5">
81-
<li
82-
v-for="(pathItem, idx) in path"
83-
:key="idx"
84-
class="font-mono text-xs"
85-
:style="{ paddingLeft: `${idx * 12}px` }"
86-
>
87-
<span v-if="idx > 0" class="text-fg-subtle me-1">└─</span>
88-
<NuxtLink
89-
:to="{
90-
name: 'package',
91-
params: {
92-
package: [
93-
...parsePackageString(pathItem).name.split('/'),
94-
'v',
95-
parsePackageString(pathItem).version,
96-
],
97-
},
98-
}"
99-
class="hover:underline"
100-
:class="idx === path.length - 1 ? 'text-fg font-medium' : 'text-fg-muted'"
101-
@click="closePopup"
86+
<UseFocusTrap :options="{ immediate: true }">
87+
<ul class="list-none m-0 p-0 space-y-0.5">
88+
<li
89+
v-for="(pathItem, idx) in path"
90+
:key="idx"
91+
class="font-mono text-xs"
92+
:style="{ paddingLeft: `${idx * 12}px` }"
10293
>
103-
{{ pathItem }}
104-
</NuxtLink>
105-
<span v-if="idx === path.length - 1" class="ms-1 text-amber-500">⚠</span>
106-
</li>
107-
</ul>
94+
<span v-if="idx > 0" class="text-fg-subtle me-1">└─</span>
95+
<NuxtLink
96+
:to="{
97+
name: 'package',
98+
params: {
99+
package: [
100+
...parsePackageString(pathItem).name.split('/'),
101+
'v',
102+
parsePackageString(pathItem).version,
103+
],
104+
},
105+
}"
106+
class="hover:underline"
107+
:class="idx === path.length - 1 ? 'text-fg font-medium' : 'text-fg-muted'"
108+
@click="closePopup"
109+
>
110+
{{ pathItem }}
111+
</NuxtLink>
112+
<span v-if="idx === path.length - 1" class="ms-1 text-amber-500">⚠</span>
113+
</li>
114+
</ul>
115+
</UseFocusTrap>
108116
</div>
109117
</div>
110118
</template>

app/components/ReadmeTocDropdown.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function handleScroll(event: Event) {
6969
}
7070
close()
7171
}
72-
useEventListener('scroll', handleScroll, true)
72+
useEventListener('scroll', handleScroll, { passive: true })
7373
7474
// Generate unique ID for accessibility
7575
const inputId = useId()

0 commit comments

Comments
 (0)