mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 01:03:03 +08:00
fix(segment-view): scroll to correct content when height is not set (#30547)
Issue number: resolves #30543 --------- ## What is the current behavior? On desktop Safari and Android the segment view is not switching to the right segment content when the height is dynamically set or read in as 0. This can be reproduced in the following StackBlitz on Android: https://6dhropnr-aheyyprl.stackblitz.io/ ## What is the new behavior? - Sets `min-height` to `1px` on `ion-segment-content` so that it continues to work with a dynamically set height - Adds an e2e test for Safari to verify the correct content is displayed when it contains a dynamically loaded image ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information Dev build: `8.6.2-dev.11752524287.1d61cd78` [Preview](https://ionic-framework-git-fw-6586-ionic1.vercel.app/src/components/segment-view/test/dynamic-height) --------- Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
This commit is contained in:
@ -9,6 +9,12 @@
|
||||
|
||||
width: 100%;
|
||||
|
||||
// Workaround for a Safari/WebKit bug where flexbox children with dynamic
|
||||
// height (e.g., height: fit-content) are not included in the scrollable area
|
||||
// when using horizontal scrolling. This is needed to make the segment view
|
||||
// scroll to the correct content.
|
||||
min-height: 1px;
|
||||
|
||||
overflow-y: scroll;
|
||||
|
||||
/* Hide scrollbar in Firefox */
|
||||
|
@ -0,0 +1,75 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Segment View - Dynamic Height</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<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>
|
||||
|
||||
<style>
|
||||
ion-segment-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
ion-segment-content:nth-of-type(1) {
|
||||
background: lightpink;
|
||||
}
|
||||
ion-segment-content:nth-of-type(2) {
|
||||
background: lightblue;
|
||||
}
|
||||
ion-segment-content:nth-of-type(3) {
|
||||
background: lightgreen;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Segment View - Dynamic Height</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-segment>
|
||||
<ion-segment-button value="first" content-id="first">
|
||||
<ion-label>First</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="second" content-id="second">
|
||||
<ion-label>Second</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="third" content-id="third">
|
||||
<ion-label>Third</ion-label>
|
||||
</ion-segment-button>
|
||||
</ion-segment>
|
||||
<ion-segment-view>
|
||||
<ion-segment-content id="first">
|
||||
Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora
|
||||
quaeritis. Summus brains sit, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris.
|
||||
Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat
|
||||
cerebella viventium. Qui animated corpse, cricket bat max brucks terribilem incessu zomby. The voodoo
|
||||
sacerdos flesh eater, suscitat mortuos comedere carnem virus. Zonbi tattered for solum oculi eorum defunctis
|
||||
go lum cerebro. Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv
|
||||
</ion-segment-content>
|
||||
<ion-segment-content id="second">
|
||||
<ion-input value="" label="Email"></ion-input>
|
||||
</ion-segment-content>
|
||||
<ion-segment-content id="third">
|
||||
<ion-img class="img-part" src="https://picsum.photos/200/300"></ion-img>
|
||||
</ion-segment-content>
|
||||
</ion-segment-view>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,85 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
/**
|
||||
* This behavior does not vary across modes/directions
|
||||
*/
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('segment-view: dynamic height'), () => {
|
||||
test('should show the third content when clicking the third button', async ({ page, skip }) => {
|
||||
// Skip this test on Chrome and Firefox
|
||||
skip.browser('firefox', 'Original issue only happens on Safari.');
|
||||
skip.browser('chromium', 'Original issue only happens on Safari.');
|
||||
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-segment-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ion-segment>
|
||||
<ion-segment-button value="first" content-id="first">
|
||||
<ion-label>First</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="second" content-id="second">
|
||||
<ion-label>Second</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="third" content-id="third">
|
||||
<ion-label>Third</ion-label>
|
||||
</ion-segment-button>
|
||||
</ion-segment>
|
||||
<ion-segment-view>
|
||||
<ion-segment-content id="first">
|
||||
Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora
|
||||
quaeritis. Summus brains sit, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum
|
||||
mauris. Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus
|
||||
comedat cerebella viventium. Qui animated corpse, cricket bat max brucks terribilem incessu zomby. The
|
||||
voodoo sacerdos flesh eater, suscitat mortuos comedere carnem virus. Zonbi tattered for solum oculi eorum
|
||||
defunctis go lum cerebro. Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv
|
||||
</ion-segment-content>
|
||||
<ion-segment-content id="second">
|
||||
<ion-input value="" label="Email"></ion-input>
|
||||
</ion-segment-content>
|
||||
<ion-segment-content id="third">
|
||||
<ion-img class="img-part" src="https://picsum.photos/200/300"></ion-img>
|
||||
</ion-segment-content>
|
||||
</ion-segment-view>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
// Click the third button
|
||||
await page.locator('ion-segment-button[value="third"]').click();
|
||||
|
||||
// Wait for the content to be scrolled
|
||||
await page.waitForChanges();
|
||||
|
||||
// Wait for the image to load and be visible
|
||||
const imgLocator = page.locator('ion-segment-content#third ion-img');
|
||||
await imgLocator.waitFor({ state: 'visible', timeout: 10000 });
|
||||
|
||||
// Wait for any layout adjustments
|
||||
await page.waitForChanges();
|
||||
|
||||
// Check that the third content is visible
|
||||
const segmentView = page.locator('ion-segment-view');
|
||||
const thirdContent = page.locator('ion-segment-content#third');
|
||||
|
||||
const viewBox = await segmentView.boundingBox();
|
||||
const contentBox = await thirdContent.boundingBox();
|
||||
|
||||
if (!viewBox || !contentBox) throw new Error('Bounding box not found');
|
||||
|
||||
// Allow a small tolerance to account for subpixel rendering,
|
||||
// scrollbars, or layout rounding differences
|
||||
const tolerance = 10;
|
||||
expect(contentBox.x).toBeGreaterThanOrEqual(viewBox.x);
|
||||
expect(contentBox.x + contentBox.width).toBeLessThanOrEqual(viewBox.x + viewBox.width + tolerance);
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user