diff --git a/addons/web/static/src/js/components/dropdown_menu.js b/addons/web/static/src/js/components/dropdown_menu.js index c536f3caba7..64c30b6500e 100644 --- a/addons/web/static/src/js/components/dropdown_menu.js +++ b/addons/web/static/src/js/components/dropdown_menu.js @@ -121,7 +121,11 @@ odoo.define('web.DropdownMenu', function (require) { * @param {MouseEvent} ev */ _onWindowClick(ev) { - if (this.state.open && !this.el.contains(ev.target)) { + if ( + this.state.open && + !this.el.contains(ev.target) && + !this.el.contains(document.activeElement) + ) { this.state.open = false; } } diff --git a/addons/web/static/src/js/components/dropdown_menu_item.js b/addons/web/static/src/js/components/dropdown_menu_item.js index bc028e17719..bcc54ab4ffb 100644 --- a/addons/web/static/src/js/components/dropdown_menu_item.js +++ b/addons/web/static/src/js/components/dropdown_menu_item.js @@ -86,7 +86,11 @@ odoo.define('web.DropdownMenuItem', function (require) { * @param {MouseEvent} ev */ _onWindowClick(ev) { - if (this.state.open && !this.el.contains(ev.target)) { + if ( + this.state.open && + !this.el.contains(ev.target) && + !this.el.contains(document.activeElement) + ) { this.state.open = false; } } diff --git a/addons/web/static/tests/components/dropdown_menu_tests.js b/addons/web/static/tests/components/dropdown_menu_tests.js index a0f00b68ef1..da0d458d680 100644 --- a/addons/web/static/tests/components/dropdown_menu_tests.js +++ b/addons/web/static/tests/components/dropdown_menu_tests.js @@ -339,5 +339,48 @@ odoo.define('web.dropdown_menu_tests', function (require) { parent.destroy(); }); + + QUnit.test("dropdown doesn't get close on mousedown inside and mouseup outside dropdown", async function (assert) { + // In this test, we simulate a case where the user clicks inside a dropdown menu item + // (e.g. in the input of the 'Save current search' item in the Favorites menu), keeps + // the click pressed, moves the cursor outside the dropdown and releases the click + // (i.e. mousedown and focus inside the item, mouseup and click outside the dropdown). + // In this case, we want to keep the dropdown menu open. + assert.expect(5); + + const items = this.items; + class Parent extends owl.Component { + constructor() { + super(...arguments); + this.items = items; + } + } + Parent.components = { DropdownMenu }; + Parent.template = owl.tags.xml` +