diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index 4023d46971c..73dc8a04cc0 100644 --- a/core/src/components/segment-view/segment-view.tsx +++ b/core/src/components/segment-view/segment-view.tsx @@ -47,6 +47,13 @@ export class SegmentView implements ComponentInterface { handleScroll(ev: Event) { const { scrollLeft, scrollWidth, clientWidth } = ev.target as HTMLElement; const max = scrollWidth - clientWidth; + // When only one content item is present max is 0 — skip to avoid NaN/Infinity scrollRatio. + // Still reset the timeout so isManualScroll isn't cleared prematurely if setContent + // started the timer and a stray scroll event arrives on a non-overflowing element. + if (max <= 0) { + this.resetScrollEndTimeout(); + return; + } const scrollRatio = (isRTL(this.el) ? -1 : 1) * (scrollLeft / max); this.ionSegmentViewScroll.emit({ diff --git a/core/src/components/segment-view/test/basic/segment-view.e2e.ts b/core/src/components/segment-view/test/basic/segment-view.e2e.ts index f3f35626eaa..a7f3afe4493 100644 --- a/core/src/components/segment-view/test/basic/segment-view.e2e.ts +++ b/core/src/components/segment-view/test/basic/segment-view.e2e.ts @@ -128,6 +128,37 @@ configs({ modes: ['md'] }).forEach(({ title, config }) => { await expect(segmentButton).toHaveClass(/segment-button-checked/); }); + test('should not emit ionSegmentViewScroll with NaN or Infinity scrollRatio when only one content item is present', async ({ + page, + }) => { + await page.setContent( + ` + + + Only + + + + Only + + `, + config + ); + + const ionSegmentViewScroll = await page.spyOnEvent('ionSegmentViewScroll'); + + // Programmatically dispatch a scroll event on the segment-view host element + // to simulate what the browser fires when scrollLeft changes. + await page.locator('ion-segment-view').evaluate((el: HTMLElement) => { + el.dispatchEvent(new Event('scroll', { bubbles: true })); + }); + + await page.waitForChanges(); + + // The max === 0 guard should prevent ionSegmentViewScroll from firing entirely. + expect(ionSegmentViewScroll).not.toHaveReceivedEvent(); + }); + test('should set correct segment button as checked and show correct content when programmatically setting the segment value', async ({ page, }) => { diff --git a/core/src/components/segment/segment.tsx b/core/src/components/segment/segment.tsx index 256ec21edae..1d2674ddb69 100644 --- a/core/src/components/segment/segment.tsx +++ b/core/src/components/segment/segment.tsx @@ -388,6 +388,7 @@ export class Segment implements ComponentInterface { const dispatchedFrom = ev.target as HTMLElement; const segmentViewEl = this.segmentViewEl as EventTarget; + const segmentEl = this.el; // Only update the indicator if the event was dispatched from the correct segment view