diff --git a/core/src/components/menu-button/test/async/index.html b/core/src/components/menu-button/test/async/index.html
new file mode 100644
index 0000000000..105b9a3b87
--- /dev/null
+++ b/core/src/components/menu-button/test/async/index.html
@@ -0,0 +1,64 @@
+
+
+
+
+ Menu - Async
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Menu - Async
+
+
+
+
+ Main Content
+
+
+
+
+
+
+
+
diff --git a/core/src/components/menu-button/test/async/menu-button.e2e.ts b/core/src/components/menu-button/test/async/menu-button.e2e.ts
new file mode 100644
index 0000000000..9d06238b19
--- /dev/null
+++ b/core/src/components/menu-button/test/async/menu-button.e2e.ts
@@ -0,0 +1,25 @@
+import { expect } from '@playwright/test';
+import { configs, test } from '@utils/test/playwright';
+
+/**
+ * This behavior does not vary across modes/directions
+ */
+configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
+ test.describe(title('menu button: async'), () => {
+ test('menu button should be visible if menu is moved', async ({ page }) => {
+ await page.goto(`/src/components/menu-button/test/async`, config);
+
+ const menu = page.locator('ion-menu');
+ const menuButton = page.locator('ion-menu-button');
+ const triggerButton = page.locator('#trigger');
+
+ await expect(menu).not.toBeAttached();
+ await expect(menuButton).toBeHidden();
+
+ await triggerButton.click();
+
+ await expect(menu).toBeAttached();
+ await expect(menuButton).toBeVisible();
+ });
+ });
+});
diff --git a/core/src/components/menu/menu.tsx b/core/src/components/menu/menu.tsx
index c010e72d2d..5072bb74cd 100644
--- a/core/src/components/menu/menu.tsx
+++ b/core/src/components/menu/menu.tsx
@@ -38,6 +38,7 @@ export class Menu implements ComponentInterface, MenuI {
private lastOnEnd = 0;
private gesture?: Gesture;
private blocker = GESTURE_CONTROLLER.createBlocker({ disableScroll: true });
+ private didLoad = false;
isAnimating = false;
width!: number;
@@ -216,6 +217,7 @@ export class Menu implements ComponentInterface, MenuI {
// register this menu with the app's menu controller
menuController._register(this);
+ this.menuChanged();
this.gesture = (await import('../../utils/gesture')).createGesture({
el: document,
@@ -237,10 +239,22 @@ export class Menu implements ComponentInterface, MenuI {
}
async componentDidLoad() {
- this.ionMenuChange.emit({ disabled: this.disabled, open: this._isOpen });
+ this.didLoad = true;
+ this.menuChanged();
this.updateState();
}
+ private menuChanged() {
+ /**
+ * Inform dependent components such as ion-menu-button
+ * that the menu is ready. Note that we only want to do this
+ * once the menu has been rendered which is why we check for didLoad.
+ */
+ if (this.didLoad) {
+ this.ionMenuChange.emit({ disabled: this.disabled, open: this._isOpen });
+ }
+ }
+
async disconnectedCallback() {
/**
* The menu should be closed when it is