diff --git a/packages/main/src/Menu.ts b/packages/main/src/Menu.ts
index 5428fa605ef..2e82baa7fb0 100644
--- a/packages/main/src/Menu.ts
+++ b/packages/main/src/Menu.ts
@@ -1,4 +1,4 @@
-import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
+import UI5Element, { type ChangeInfo } from "@ui5/webcomponents-base/dist/UI5Element.js";
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
@@ -234,6 +234,13 @@ class Menu extends UI5Element {
@property({ converter: DOMReferenceConverter })
opener?: HTMLElement | string;
+ /**
+ * Indicates if the menu item has a submenu.
+ * @private
+ */
+ @property({ type: Boolean, noAttribute: true })
+ _newItemsAdded?: boolean;
+
/**
* Defines the items of this component.
*
@@ -277,6 +284,27 @@ class Menu extends UI5Element {
this._menuItems.forEach(item => {
item._siblingsWithIcon = siblingsWithIcon;
});
+
+ if (this._newItemsAdded) {
+ if (this._menuItems.length > 0) {
+ const hasSelectedItem = this._menuItems.some(item => item.selected);
+
+ if (!hasSelectedItem) {
+ this._menuItems[0].focus();
+ }
+
+ if (this._menuItems[0].focused) {
+ this._newItemsAdded = false;
+ }
+ }
+ }
+ }
+
+ onInvalidation(changeInfo: ChangeInfo) {
+ // if the change is due to a new item being added, focus the first item
+ if (changeInfo.reason === "children" && changeInfo.type === "slot") {
+ this._newItemsAdded = true;
+ }
}
_close() {
diff --git a/packages/main/src/MenuItem.ts b/packages/main/src/MenuItem.ts
index 8c47629bd6a..071f6c3bdd1 100644
--- a/packages/main/src/MenuItem.ts
+++ b/packages/main/src/MenuItem.ts
@@ -7,6 +7,7 @@ import AriaHasPopup from "@ui5/webcomponents-base/dist/types/AriaHasPopup.js";
import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js";
import "@ui5/webcomponents-icons/dist/nav-back.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
+import type { ChangeInfo } from "@ui5/webcomponents-base/dist/UI5Element.js";
import type { ListItemAccessibilityAttributes } from "./ListItem.js";
import ListItem from "./ListItem.js";
import ResponsivePopover from "./ResponsivePopover.js";
@@ -166,6 +167,13 @@ class MenuItem extends ListItem implements IMenuItem {
@property({ type: Boolean, noAttribute: true })
_siblingsWithIcon = false;
+ /**
+ * Indicates if the menu item has a submenu.
+ * @private
+ */
+ @property({ type: Boolean, noAttribute: true })
+ _newItemsAdded?: boolean;
+
/**
* Defines the items of this component.
*
@@ -259,6 +267,27 @@ class MenuItem extends ListItem implements IMenuItem {
this._menuItems.forEach(item => {
item._siblingsWithIcon = siblingsWithIcon;
});
+
+ if (this._newItemsAdded) {
+ if (this._menuItems.length > 0) {
+ const hasSelectedItem = this._menuItems.some(item => item.selected);
+
+ if (!hasSelectedItem) {
+ this._menuItems[0].focus();
+ }
+
+ if (this._menuItems[0].focused) {
+ this._newItemsAdded = false;
+ }
+ }
+ }
+ }
+
+ onInvalidation(changeInfo: ChangeInfo) {
+ // if the change is due to a new item being added, focus the first item
+ if (changeInfo.reason === "children" && changeInfo.type === "slot") {
+ this._newItemsAdded = true;
+ }
}
get _focusable() {
diff --git a/packages/main/test/pages/Menu.html b/packages/main/test/pages/Menu.html
index 5619953ca74..be000280d85 100644
--- a/packages/main/test/pages/Menu.html
+++ b/packages/main/test/pages/Menu.html
@@ -21,13 +21,13 @@
-
+
@@ -43,6 +43,9 @@
+
+
@@ -119,6 +122,9 @@
+
+ Delayed
+