Skip to content

Commit 1c7305d

Browse files
liamdebeasiaveryjohnston
authored andcommitted
fix(menu): menu no longer disappears with multiple split panes (#28370)
Issue number: resolves #18683, resolves #15538, resolves #22341 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> 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? <!-- Please describe the behavior or changes that are being added by this PR. --> - Menus are only hidden when its parent split pane changes visibility ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Dev build: `7.5.1-dev.11697568647.1ac87d08` --------- Co-authored-by: Amanda Johnston <[email protected]>
1 parent 96a228b commit 1c7305d

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

core/src/components/menu/menu.tsx

+14
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,20 @@ export class Menu implements ComponentInterface, MenuI {
289289

290290
@Listen('ionSplitPaneVisible', { target: 'body' })
291291
onSplitPaneChanged(ev: CustomEvent) {
292+
const { target } = ev;
293+
const closestSplitPane = this.el.closest('ion-split-pane');
294+
295+
/**
296+
* Menu listens on the body for "ionSplitPaneVisible".
297+
* However, this means the callback will run any time
298+
* a SplitPane changes visibility. As a result, we only want
299+
* Menu's visibility state to update if its parent SplitPane
300+
* changes visibility.
301+
*/
302+
if (target !== closestSplitPane) {
303+
return;
304+
}
305+
292306
this.isPaneVisible = ev.detail.isPane(this.el);
293307
this.updateState();
294308
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Split Pane - Multiple</title>
6+
<meta
7+
name="viewport"
8+
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
9+
/>
10+
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
11+
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
12+
<script src="../../../../../scripts/testing/scripts.js"></script>
13+
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
14+
</head>
15+
<body>
16+
<ion-split-pane id="pane-one" content-id="content-one">
17+
<ion-menu id="pane-one-menu-one" side="start" content-id="content-one">
18+
<div class="ion-padding">Split One Menu One</div>
19+
</ion-menu>
20+
21+
<div class="ion-page" id="content-one">
22+
<ion-content class="ion-padding">
23+
Page Content One
24+
<button id="show-pane-two" onclick="showSecondPane()">Show Second Pane</button>
25+
</ion-content>
26+
</div>
27+
28+
<ion-menu id="pane-one-menu-two" side="end" content-id="content-one">
29+
<div class="ion-padding">Split One Menu Two</div>
30+
</ion-menu>
31+
</ion-split-pane>
32+
33+
<ion-split-pane id="pane-two" content-id="content-two" disabled="true" class="ion-page-hidden">
34+
<ion-menu id="pane-two-menu-one" side="start" content-id="content-two">
35+
<div class="ion-padding">Split Two Menu One</div>
36+
</ion-menu>
37+
38+
<div class="ion-page" id="content-two">
39+
<ion-content class="ion-padding">
40+
Page Content Two
41+
<button id="show-pane-one" onclick="showFirstPane()">Show First Pane</button>
42+
</ion-content>
43+
</div>
44+
45+
<ion-menu id="pane-two-menu-two" side="end" content-id="content-two">
46+
<div class="ion-padding">Split Two Menu Two</div>
47+
</ion-menu>
48+
</ion-split-pane>
49+
50+
<script>
51+
const splitPaneOne = document.querySelector('ion-split-pane#pane-one');
52+
const splitPaneTwo = document.querySelector('ion-split-pane#pane-two');
53+
const showSecondPane = () => {
54+
splitPaneOne.disabled = true;
55+
splitPaneOne.classList.add('ion-page-hidden');
56+
57+
splitPaneTwo.disabled = false;
58+
splitPaneTwo.classList.remove('ion-page-hidden');
59+
};
60+
const showFirstPane = () => {
61+
splitPaneOne.disabled = false;
62+
splitPaneOne.classList.remove('ion-page-hidden');
63+
64+
splitPaneTwo.disabled = true;
65+
splitPaneTwo.classList.add('ion-page-hidden');
66+
};
67+
</script>
68+
</body>
69+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test, Viewports } from '@utils/test/playwright';
3+
4+
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
5+
test.describe(title('split-pane: multiple'), () => {
6+
test('using multiple split panes should not hide a menu in another split pane', async ({ page }) => {
7+
test.info().annotations.push({
8+
type: 'issue',
9+
description: 'https://github.com/ionic-team/ionic-framework/issues/18683',
10+
});
11+
12+
await page.setViewportSize(Viewports.large);
13+
await page.goto(`/src/components/split-pane/test/multiple`, config);
14+
15+
const paneOneMenuOne = page.locator('ion-menu#pane-one-menu-one');
16+
const paneOneMenuTwo = page.locator('ion-menu#pane-one-menu-two');
17+
18+
const paneTwoMenuOne = page.locator('ion-menu#pane-two-menu-one');
19+
const paneTwoMenuTwo = page.locator('ion-menu#pane-two-menu-two');
20+
21+
const showPaneOne = page.locator('button#show-pane-one');
22+
const showPaneTwo = page.locator('button#show-pane-two');
23+
24+
await expect(paneOneMenuOne).toBeVisible();
25+
await expect(paneOneMenuTwo).toBeVisible();
26+
27+
await showPaneTwo.click();
28+
29+
await expect(paneTwoMenuOne).toBeVisible();
30+
await expect(paneTwoMenuTwo).toBeVisible();
31+
32+
await showPaneOne.click();
33+
34+
await expect(paneOneMenuOne).toBeVisible();
35+
await expect(paneOneMenuTwo).toBeVisible();
36+
});
37+
});
38+
});

0 commit comments

Comments
 (0)