From 5a30082546cb19eb98128ca9091b35094841d4f2 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 19 Oct 2023 12:40:25 -0400 Subject: [PATCH] fix(menu): menu no longer disappears with multiple split panes (#28370) Issue number: resolves #18683, resolves #15538, resolves #22341 --------- ## What is the current behavior? Menus in a split pane are hidden when a second split pane is mounted/made visible. This is because the `onSplitPaneChanged` callback does not take into account whether the it is a child of the split pane that emitted `ionSplitPaneVisible`. When split pane 2 is shown, that causes the menu is split pane 1 to hide. When split pane 1 is shown, the menu inside of it _is_ shown. However, since split pane 2 is then hidden that component also emits `ionSplitPaneVisible`, causing the menu inside of split pane 1 to hide. ## What is the new behavior? - Menus are only hidden when its parent split pane changes visibility ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information Dev build: `7.5.1-dev.11697568647.1ac87d08` --------- Co-authored-by: Amanda Johnston <90629384+amandaejohnston@users.noreply.github.com> --- core/src/components/menu/menu.tsx | 14 ++++ .../split-pane/test/multiple/index.html | 69 +++++++++++++++++++ .../test/multiple/split-pane.e2e.ts | 38 ++++++++++ 3 files changed, 121 insertions(+) create mode 100644 core/src/components/split-pane/test/multiple/index.html create mode 100644 core/src/components/split-pane/test/multiple/split-pane.e2e.ts diff --git a/core/src/components/menu/menu.tsx b/core/src/components/menu/menu.tsx index 1dc46a41e0..db40853b88 100644 --- a/core/src/components/menu/menu.tsx +++ b/core/src/components/menu/menu.tsx @@ -289,6 +289,20 @@ export class Menu implements ComponentInterface, MenuI { @Listen('ionSplitPaneVisible', { target: 'body' }) onSplitPaneChanged(ev: CustomEvent) { + const { target } = ev; + const closestSplitPane = this.el.closest('ion-split-pane'); + + /** + * Menu listens on the body for "ionSplitPaneVisible". + * However, this means the callback will run any time + * a SplitPane changes visibility. As a result, we only want + * Menu's visibility state to update if its parent SplitPane + * changes visibility. + */ + if (target !== closestSplitPane) { + return; + } + this.isPaneVisible = ev.detail.isPane(this.el); this.updateState(); } diff --git a/core/src/components/split-pane/test/multiple/index.html b/core/src/components/split-pane/test/multiple/index.html new file mode 100644 index 0000000000..cc2cb49092 --- /dev/null +++ b/core/src/components/split-pane/test/multiple/index.html @@ -0,0 +1,69 @@ + + + + + Split Pane - Multiple + + + + + + + + + +
Split One Menu One
+
+ +
+ + Page Content One + + +
+ + +
Split One Menu Two
+
+
+ + + +
Split Two Menu One
+
+ +
+ + Page Content Two + + +
+ + +
Split Two Menu Two
+
+
+ + + + diff --git a/core/src/components/split-pane/test/multiple/split-pane.e2e.ts b/core/src/components/split-pane/test/multiple/split-pane.e2e.ts new file mode 100644 index 0000000000..3abaab7695 --- /dev/null +++ b/core/src/components/split-pane/test/multiple/split-pane.e2e.ts @@ -0,0 +1,38 @@ +import { expect } from '@playwright/test'; +import { configs, test, Viewports } from '@utils/test/playwright'; + +configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => { + test.describe(title('split-pane: multiple'), () => { + test('using multiple split panes should not hide a menu in another split pane', async ({ page }) => { + test.info().annotations.push({ + type: 'issue', + description: 'https://github.com/ionic-team/ionic-framework/issues/18683', + }); + + await page.setViewportSize(Viewports.large); + await page.goto(`/src/components/split-pane/test/multiple`, config); + + const paneOneMenuOne = page.locator('ion-menu#pane-one-menu-one'); + const paneOneMenuTwo = page.locator('ion-menu#pane-one-menu-two'); + + const paneTwoMenuOne = page.locator('ion-menu#pane-two-menu-one'); + const paneTwoMenuTwo = page.locator('ion-menu#pane-two-menu-two'); + + const showPaneOne = page.locator('button#show-pane-one'); + const showPaneTwo = page.locator('button#show-pane-two'); + + await expect(paneOneMenuOne).toBeVisible(); + await expect(paneOneMenuTwo).toBeVisible(); + + await showPaneTwo.click(); + + await expect(paneTwoMenuOne).toBeVisible(); + await expect(paneTwoMenuTwo).toBeVisible(); + + await showPaneOne.click(); + + await expect(paneOneMenuOne).toBeVisible(); + await expect(paneOneMenuTwo).toBeVisible(); + }); + }); +});