diff --git a/addons/web/static/src/webclient/navbar/navbar.js b/addons/web/static/src/webclient/navbar/navbar.js
index 7c4c7dbf259..c869b476641 100644
--- a/addons/web/static/src/webclient/navbar/navbar.js
+++ b/addons/web/static/src/webclient/navbar/navbar.js
@@ -7,11 +7,25 @@ import { registry } from "@web/core/registry";
import { debounce } from "@web/core/utils/timing";
import { ErrorHandler } from "@web/core/utils/components";
-import { Component, onWillDestroy, onWillUnmount, useExternalListener, useEffect, useRef } from "@odoo/owl";
+import {
+ Component,
+ onWillDestroy,
+ onWillUnmount,
+ useExternalListener,
+ useEffect,
+ useRef,
+} from "@odoo/owl";
const systrayRegistry = registry.category("systray");
const getBoundingClientRect = Element.prototype.getBoundingClientRect;
+class NavBarDropdownItem extends DropdownItem {}
+NavBarDropdownItem.template = "web.NavBar.DropdownItem";
+NavBarDropdownItem.props = {
+ ...DropdownItem.props,
+ style: { type: String, optional: true },
+};
+
export class MenuDropdown extends Dropdown {
setup() {
super.setup();
@@ -201,5 +215,5 @@ export class NavBar extends Component {
}
}
NavBar.template = "web.NavBar";
-NavBar.components = { Dropdown, DropdownItem, MenuDropdown, ErrorHandler };
+NavBar.components = { Dropdown, DropdownItem: NavBarDropdownItem, MenuDropdown, ErrorHandler };
NavBar.props = {};
diff --git a/addons/web/static/src/webclient/navbar/navbar.scss b/addons/web/static/src/webclient/navbar/navbar.scss
index 638a6c3e3b3..f2b373c8e43 100644
--- a/addons/web/static/src/webclient/navbar/navbar.scss
+++ b/addons/web/static/src/webclient/navbar/navbar.scss
@@ -58,6 +58,14 @@
border-radius: $o-navbar-dropdown-menu-border-radius;
}
+ .dropdown-header.dropdown-menu_group {
+ margin-top: 0;
+ }
+
+ .dropdown-item + .dropdown-header:not(.o_more_dropdown_section_group) {
+ margin-top: .3em;
+ }
+
.o_dropdown_menu_group_entry.dropdown-item {
padding-left: $o-dropdown-hpadding * 1.5;
diff --git a/addons/web/static/src/webclient/navbar/navbar.xml b/addons/web/static/src/webclient/navbar/navbar.xml
index cd2be93347f..fa73c6da87a 100644
--- a/addons/web/static/src/webclient/navbar/navbar.xml
+++ b/addons/web/static/src/webclient/navbar/navbar.xml
@@ -95,6 +95,7 @@
+
@@ -110,29 +111,34 @@
+
+
+ props.style
+
+
+
+
-
-
+
+
+
+
+
@@ -160,6 +166,7 @@
/>
+
diff --git a/addons/web/static/tests/webclient/navbar_tests.js b/addons/web/static/tests/webclient/navbar_tests.js
index 7a7566c160b..924fbbff965 100644
--- a/addons/web/static/tests/webclient/navbar_tests.js
+++ b/addons/web/static/tests/webclient/navbar_tests.js
@@ -86,6 +86,43 @@ QUnit.test("href attribute on apps menu items", async (assert) => {
assert.strictEqual(dropdownItem.getAttribute("href"), "#menu_id=1&action=339");
});
+QUnit.test("many sublevels in app menu items", async (assert) => {
+ baseConfig.serverData.menus = {
+ root: { id: "root", children: [1], name: "root", appID: "root" },
+ 1: { id: 1, children: [2], name: "My app", appID: 1 },
+ 2: { id: 2, children: [3], name: "My menu", appID: 1 },
+ 3: { id: 3, children: [4], name: "My submenu 1", appID: 1 },
+ 4: { id: 4, children: [5], name: "My submenu 2", appID: 1 },
+ 5: { id: 5, children: [6], name: "My submenu 3", appID: 1 },
+ 6: { id: 6, children: [7], name: "My submenu 4", appID: 1 },
+ 7: { id: 7, children: [8], name: "My submenu 5", appID: 1 },
+ 8: { id: 8, children: [9], name: "My submenu 6", appID: 1 },
+ 9: { id: 9, children: [], name: "My submenu 7", appID: 1 },
+ };
+ const env = await makeTestEnv(baseConfig);
+ env.services.menu.setCurrentMenu(1);
+ await mount(NavBar, target, { env });
+ const firstSectionMenu = target.querySelector(".o_menu_sections .dropdown");
+ await click(firstSectionMenu, "button.dropdown-toggle");
+ const menuChildren = [...firstSectionMenu.querySelectorAll(".dropdown-menu > *")];
+ assert.deepEqual(
+ menuChildren.map((el) => ({
+ text: el.textContent,
+ paddingLeft: el.style.paddingLeft,
+ tagName: el.tagName,
+ })),
+ [
+ { text: "My submenu 1", paddingLeft: "20px", tagName: "DIV" },
+ { text: "My submenu 2", paddingLeft: "32px", tagName: "DIV" },
+ { text: "My submenu 3", paddingLeft: "44px", tagName: "DIV" },
+ { text: "My submenu 4", paddingLeft: "56px", tagName: "DIV" },
+ { text: "My submenu 5", paddingLeft: "68px", tagName: "DIV" },
+ { text: "My submenu 6", paddingLeft: "80px", tagName: "DIV" },
+ { text: "My submenu 7", paddingLeft: "92px", tagName: "A" },
+ ]
+ );
+});
+
QUnit.test("data-menu-xmlid attribute on AppsMenu items", async (assert) => {
baseConfig.serverData.menus = {
root: { id: "root", children: [1, 2], name: "root", appID: "root" },