From d14311fb65ae3de7ba7578791ce1ea44f186c413 Mon Sep 17 00:00:00 2001 From: Brandy Smith Date: Wed, 16 Jul 2025 12:06:37 -0400 Subject: [PATCH] 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> --- .../segment-content/segment-content.scss | 6 ++ .../test/dynamic-height/index.html | 75 ++++++++++++++++ .../test/dynamic-height/segment-view.e2e.ts | 85 +++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 core/src/components/segment-view/test/dynamic-height/index.html create mode 100644 core/src/components/segment-view/test/dynamic-height/segment-view.e2e.ts diff --git a/core/src/components/segment-content/segment-content.scss b/core/src/components/segment-content/segment-content.scss index 38616a7d90..1abfe6171f 100644 --- a/core/src/components/segment-content/segment-content.scss +++ b/core/src/components/segment-content/segment-content.scss @@ -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 */ diff --git a/core/src/components/segment-view/test/dynamic-height/index.html b/core/src/components/segment-view/test/dynamic-height/index.html new file mode 100644 index 0000000000..86c64db018 --- /dev/null +++ b/core/src/components/segment-view/test/dynamic-height/index.html @@ -0,0 +1,75 @@ + + + + + Segment View - Dynamic Height + + + + + + + + + + + + + + + Segment View - Dynamic Height + + + + + + + First + + + Second + + + Third + + + + + 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 + + + + + + + + + + + + diff --git a/core/src/components/segment-view/test/dynamic-height/segment-view.e2e.ts b/core/src/components/segment-view/test/dynamic-height/segment-view.e2e.ts new file mode 100644 index 0000000000..add7d587e7 --- /dev/null +++ b/core/src/components/segment-view/test/dynamic-height/segment-view.e2e.ts @@ -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( + ` + + + + + First + + + Second + + + Third + + + + + 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 + + + + + + + + + `, + 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); + }); + }); +});