Skip to content

Commit 300693e

Browse files
committed
fix(VMenu): avoid scrolling to the off-screen menu
1 parent 85f9c33 commit 300693e

File tree

1 file changed

+16
-0
lines changed
  • packages/vuetify/src/components/VMenu

1 file changed

+16
-0
lines changed

packages/vuetify/src/components/VMenu/VMenu.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,24 @@ export const VMenu = genericComponent<OverlaySlots>()({
110110
})
111111
onDeactivated(() => isActive.value = false)
112112

113+
let focusTrapSuppressed = false
114+
let focusTrapSuppressionTimeout = -1
115+
116+
async function onPointerdown () {
117+
focusTrapSuppressed = true
118+
focusTrapSuppressionTimeout = window.setTimeout(() => {
119+
focusTrapSuppressed = false
120+
}, 100)
121+
}
122+
113123
async function onFocusIn (e: FocusEvent) {
114124
const before = e.relatedTarget as HTMLElement | null
115125
const after = e.target as HTMLElement | null
116126

117127
await nextTick()
118128

119129
if (
130+
!focusTrapSuppressed &&
120131
isActive.value &&
121132
before !== after &&
122133
overlay.value?.contentEl &&
@@ -129,18 +140,23 @@ export const VMenu = genericComponent<OverlaySlots>()({
129140
) {
130141
const focusable = focusableChildren(overlay.value.contentEl)
131142
focusable[0]?.focus()
143+
144+
document.removeEventListener('pointerdown', onPointerdown)
132145
}
133146
}
134147

135148
watch(isActive, val => {
136149
if (val) {
137150
parent?.register()
138151
if (IN_BROWSER && !props.disableInitialFocus) {
152+
document.addEventListener('pointerdown', onPointerdown)
139153
document.addEventListener('focusin', onFocusIn, { once: true })
140154
}
141155
} else {
142156
parent?.unregister()
143157
if (IN_BROWSER) {
158+
clearTimeout(focusTrapSuppressionTimeout)
159+
document.removeEventListener('pointerdown', onPointerdown)
144160
document.removeEventListener('focusin', onFocusIn)
145161
}
146162
}

0 commit comments

Comments
 (0)