Skip to content

Commit 6d07867

Browse files
committed
fix(VMenu): avoid scrolling to the off-screen menu
1 parent 92f8a3c commit 6d07867

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
@@ -109,13 +109,24 @@ export const VMenu = genericComponent<OverlaySlots>()({
109109
})
110110
onDeactivated(() => isActive.value = false)
111111

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

116126
await nextTick()
117127

118128
if (
129+
!focusTrapSuppressed &&
119130
isActive.value &&
120131
before !== after &&
121132
overlay.value?.contentEl &&
@@ -128,18 +139,23 @@ export const VMenu = genericComponent<OverlaySlots>()({
128139
) {
129140
const focusable = focusableChildren(overlay.value.contentEl)
130141
focusable[0]?.focus()
142+
143+
document.removeEventListener('pointerdown', onPointerdown)
131144
}
132145
}
133146

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

0 commit comments

Comments
 (0)