test(menu): safe area and proper var reset (#28177)
Issue number: N/A --------- <!-- 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. --> - There are no tests for menu when safe area is applied. - The safe area variables on menu weren't being reset properly to allow easy local customization. Currently, some of the variables are being set to `env()`. This is the same structure that is being used in core. However, this doesn't prevents users from mocking the safe area when using `--ion-safe-area-left: 50px` on `html`. It makes it hard to create tests to validate that padding is being applied to the safe area. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Tests have been added. - The safe area variables on menu are now being reset to use the values from `:root`. The variables are being `unset` in order for the variables to [default to parent styles](https://stackoverflow.com/a/69491310/5374225). Since core styles has already declared the variables, then developers can use `--ion-safe-area-left: 50px` on `html`. ## 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. --> N/A --------- Co-authored-by: ionitron <hi@ionicframework.com>
@ -83,12 +83,14 @@
|
|||||||
* Otherwise, the content will have less space on both sides.
|
* Otherwise, the content will have less space on both sides.
|
||||||
*
|
*
|
||||||
* RTL:
|
* RTL:
|
||||||
* The right side of the menu touches the screen edge. The safe area padding has
|
* The right side of the menu touches the screen edge.
|
||||||
* already been set in the core styles, so there's no need to set it again.
|
* The right side needs to revert back to the default value that was set in the core styles, so we unset it here.
|
||||||
|
* This would keep the variable consistent with the core styles.
|
||||||
|
* Additionally, it would continue to allow users to override the variable if they choose to.
|
||||||
* The left side of the menu is not touching the screen edge. Padding is not
|
* The left side of the menu is not touching the screen edge. Padding is not
|
||||||
* applied to the left side of the menu. A value of 0 is set.
|
* applied to the left side of the menu. A value of 0 is set.
|
||||||
*/
|
*/
|
||||||
--ion-safe-area-right: env(safe-area-inset-right);
|
--ion-safe-area-right: unset;
|
||||||
--ion-safe-area-left: 0px;
|
--ion-safe-area-left: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,12 +120,14 @@
|
|||||||
* Otherwise, the content will have less space on both sides.
|
* Otherwise, the content will have less space on both sides.
|
||||||
*
|
*
|
||||||
* RTL:
|
* RTL:
|
||||||
* The left side of the menu touches the screen edge. The safe area padding has
|
* The left side of the menu touches the screen edge.
|
||||||
* already been set in the core styles, so there's no need to set it again.
|
* The left side needs to revert back to the default value that was set in the core styles, so we unset it here.
|
||||||
|
* This would keep the variable consistent with the core styles.
|
||||||
|
* Additionally, it would continue to allow users to override the variable if they choose to.
|
||||||
* The right side of the menu is not touching the screen edge. Padding is not
|
* The right side of the menu is not touching the screen edge. Padding is not
|
||||||
* applied to the right side of the menu. A value of 0 is set.
|
* applied to the right side of the menu. A value of 0 is set.
|
||||||
*/
|
*/
|
||||||
--ion-safe-area-left: env(safe-area-inset-left);
|
--ion-safe-area-left: unset;
|
||||||
--ion-safe-area-right: 0px;
|
--ion-safe-area-right: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
81
core/src/components/menu/test/safe-area/index.html
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Menu - Safe Area Padding</title>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
|
||||||
|
/>
|
||||||
|
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||||
|
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||||
|
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||||
|
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||||
|
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||||
|
<script type="module">
|
||||||
|
import { menuController } from '../../../../dist/ionic/index.esm.js';
|
||||||
|
window.menuController = menuController;
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--ion-safe-area-left: 60px;
|
||||||
|
--ion-safe-area-right: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<ion-app>
|
||||||
|
<ion-menu side="start" menu-id="start-menu" content-id="main">
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar color="primary">
|
||||||
|
<ion-title>This is the title for a start menu</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<ion-list>
|
||||||
|
<ion-item>Menu Item</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
</ion-content>
|
||||||
|
</ion-menu>
|
||||||
|
|
||||||
|
<ion-menu side="end" menu-id="end-menu" content-id="main">
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar color="danger">
|
||||||
|
<ion-title>This is the title for an end menu</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<ion-list>
|
||||||
|
<ion-item>Menu Item</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
</ion-content>
|
||||||
|
</ion-menu>
|
||||||
|
|
||||||
|
<div class="ion-page" id="main">
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>Menu - Safe Area Padding</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content class="ion-padding">
|
||||||
|
<ion-button expand="block" id="open-start" onclick="openStart()">Open Start Menu</ion-button>
|
||||||
|
<ion-button expand="block" id="open-end" onclick="openEnd()">Open End Menu</ion-button>
|
||||||
|
</ion-content>
|
||||||
|
</div>
|
||||||
|
</ion-app>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
async function openStart() {
|
||||||
|
// Open the menu by menu-id
|
||||||
|
await menuController.enable(true, 'start-menu');
|
||||||
|
await menuController.open('start-menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openEnd() {
|
||||||
|
// Open the menu by side
|
||||||
|
await menuController.open('end');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
101
core/src/components/menu/test/safe-area/menu.e2e.ts
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import { expect } from '@playwright/test';
|
||||||
|
import { configs, test } from '@utils/test/playwright';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This behavior does not vary across modes.
|
||||||
|
*/
|
||||||
|
configs({ modes: ['md'] }).forEach(({ title, config, screenshot }) => {
|
||||||
|
test.describe(title('menu: safe area'), () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await page.goto(`/src/components/menu/test/safe-area`, config);
|
||||||
|
});
|
||||||
|
test.describe('side: start', () => {
|
||||||
|
test('should render with safe area when notch is on the left', async ({ page }) => {
|
||||||
|
const ionDidOpen = await page.spyOnEvent('ionDidOpen');
|
||||||
|
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const style = document.querySelector('style');
|
||||||
|
style!.innerHTML = `
|
||||||
|
:root {
|
||||||
|
--ion-safe-area-left: 50px !important;
|
||||||
|
--ion-safe-area-right: 10px !important;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.click('#open-start');
|
||||||
|
await ionDidOpen.next();
|
||||||
|
|
||||||
|
const startMenu = page.locator('[menu-id="start-menu"]');
|
||||||
|
await expect(startMenu).toHaveClass(/show-menu/);
|
||||||
|
|
||||||
|
await expect(page).toHaveScreenshot(screenshot(`menu-start-safe-area-left-notch`));
|
||||||
|
});
|
||||||
|
test('should render with safe area when notch is on the right', async ({ page }) => {
|
||||||
|
const ionDidOpen = await page.spyOnEvent('ionDidOpen');
|
||||||
|
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const style = document.querySelector('style');
|
||||||
|
style!.innerHTML = `
|
||||||
|
:root {
|
||||||
|
--ion-safe-area-left: 10px !important;
|
||||||
|
--ion-safe-area-right: 50px !important;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.click('#open-start');
|
||||||
|
await ionDidOpen.next();
|
||||||
|
|
||||||
|
const startMenu = page.locator('[menu-id="start-menu"]');
|
||||||
|
await expect(startMenu).toHaveClass(/show-menu/);
|
||||||
|
|
||||||
|
await expect(page).toHaveScreenshot(screenshot(`menu-start-safe-area-right-notch`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test.describe('side: end', () => {
|
||||||
|
test('should render with safe area when notch is on the left', async ({ page }) => {
|
||||||
|
const ionDidOpen = await page.spyOnEvent('ionDidOpen');
|
||||||
|
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const style = document.querySelector('style');
|
||||||
|
style!.innerHTML = `
|
||||||
|
:root {
|
||||||
|
--ion-safe-area-left: 50px !important;
|
||||||
|
--ion-safe-area-right: 10px !important;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.click('#open-end');
|
||||||
|
await ionDidOpen.next();
|
||||||
|
|
||||||
|
const endMenu = page.locator('[menu-id="end-menu"]');
|
||||||
|
await expect(endMenu).toHaveClass(/show-menu/);
|
||||||
|
|
||||||
|
await expect(page).toHaveScreenshot(screenshot(`menu-end-safe-area-left-notch`));
|
||||||
|
});
|
||||||
|
test('should render with safe area when notch is on the right', async ({ page }) => {
|
||||||
|
const ionDidOpen = await page.spyOnEvent('ionDidOpen');
|
||||||
|
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const style = document.querySelector('style');
|
||||||
|
style!.innerHTML = `
|
||||||
|
:root {
|
||||||
|
--ion-safe-area-left: 10px !important;
|
||||||
|
--ion-safe-area-right: 50px !important;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.click('#open-end');
|
||||||
|
await ionDidOpen.next();
|
||||||
|
|
||||||
|
const endMenu = page.locator('[menu-id="end-menu"]');
|
||||||
|
await expect(endMenu).toHaveClass(/show-menu/);
|
||||||
|
|
||||||
|
await expect(page).toHaveScreenshot(screenshot(`menu-end-safe-area-right-notch`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 6.9 KiB |