diff --git a/resources/js/menu.js b/resources/js/menu.js index 1b35a7f1..b6144882 100644 --- a/resources/js/menu.js +++ b/resources/js/menu.js @@ -45,7 +45,9 @@ const ITEMS = '[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradi // A popover="auto" closes on the press that lands on its trigger, and the click that follows // would open it again. A close this recent is taken as that press. It is timed from // `beforetoggle`, which fires as the popover closes: `toggle` is queued, and arrives after that -// click. +// click. Only a close the browser made on its own (light dismiss) sets it — `close()` marks its +// own as explicit, so a keyboard command that shuts a menu never guards against reopening it a +// moment later, only the browser's own light dismiss racing the click it precedes does. const REOPEN_GUARD_MS = 250 // A submenu opens after the pointer has rested on its item for a moment, and closes a moment after @@ -56,6 +58,7 @@ const HOVER_CLOSE_MS = 320 const menu = () => ({ closedAt: -Infinity, + closingExplicitly: false, anchored: null, returnFocus: true, focusWasInside: false, @@ -104,7 +107,11 @@ const menu = () => ({ this.focusWasInside = event.newState === 'closed' && menu.contains(document.activeElement) if (event.newState === 'closed') { - this.closedAt = performance.now() + if (!this.closingExplicitly) { + this.closedAt = performance.now() + } + + this.closingExplicitly = false } }) @@ -336,6 +343,7 @@ const menu = () => ({ } if (this.$refs.menu.matches(':popover-open')) { + this.closingExplicitly = true this.$refs.menu.hidePopover() }