@@ -109,6 +109,16 @@ 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
@@ -119,27 +129,38 @@ export const VMenu = genericComponent<OverlaySlots>()({
119129 isActive . value &&
120130 before !== after &&
121131 overlay . value ?. contentEl &&
122- // We're the topmost menu
123- overlay . value ?. globalTop &&
132+ // We're the menu without open submenus or overlays
133+ overlay . value ?. localTop &&
124134 // It isn't the document or the menu body
125135 ! [ document , overlay . value . contentEl ] . includes ( after ! ) &&
126136 // It isn't inside the menu body
127137 ! overlay . value . contentEl . contains ( after )
128138 ) {
129- const focusable = focusableChildren ( overlay . value . contentEl )
130- focusable [ 0 ] ?. focus ( )
139+ if ( focusTrapSuppressed ) {
140+ if ( ! props . openOnHover && ! overlay . value . activatorEl ?. contains ( after ) ) {
141+ isActive . value = false
142+ }
143+ } else {
144+ const focusable = focusableChildren ( overlay . value . contentEl )
145+ focusable [ 0 ] ?. focus ( )
146+
147+ document . removeEventListener ( 'pointerdown' , onPointerdown )
148+ }
131149 }
132150 }
133151
134152 watch ( isActive , val => {
135153 if ( val ) {
136154 parent ?. register ( )
137155 if ( IN_BROWSER && ! props . disableInitialFocus ) {
156+ document . addEventListener ( 'pointerdown' , onPointerdown )
138157 document . addEventListener ( 'focusin' , onFocusIn , { once : true } )
139158 }
140159 } else {
141160 parent ?. unregister ( )
142161 if ( IN_BROWSER ) {
162+ clearTimeout ( focusTrapSuppressionTimeout )
163+ document . removeEventListener ( 'pointerdown' , onPointerdown )
143164 document . removeEventListener ( 'focusin' , onFocusIn )
144165 }
145166 }
0 commit comments