Skip to content

Commit 73cadb1

Browse files
fix(segment-view): prevent NaN/Infinity scrollRatio when a single content item is present (#31113)
Issue number: resolves internal --------- <!-- 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. --> Currently if there is a single content item present the `scrollRatio` is computed as `NaN` or `Infinity` resulting in a console error. <img width="833" height="434" alt="Screenshot 2026-05-05 at 1 42 51 PM" src="https://github.com/user-attachments/assets/242975a5-d03f-4947-b740-0e6069de27b7" /> ## What is the new behavior? Updates `handleScroll` in `ion-segment-view` to skip `handleScroll` if `max <= 0` ## Does this introduce a breaking change? - [ ] Yes - [ ] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. -->
1 parent 20cae5b commit 73cadb1

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

core/src/components/segment-view/segment-view.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ export class SegmentView implements ComponentInterface {
4747
handleScroll(ev: Event) {
4848
const { scrollLeft, scrollWidth, clientWidth } = ev.target as HTMLElement;
4949
const max = scrollWidth - clientWidth;
50+
// When only one content item is present max is 0 — skip to avoid NaN/Infinity scrollRatio.
51+
// Still reset the timeout so isManualScroll isn't cleared prematurely if setContent
52+
// started the timer and a stray scroll event arrives on a non-overflowing element.
53+
if (max <= 0) {
54+
this.resetScrollEndTimeout();
55+
return;
56+
}
5057
const scrollRatio = (isRTL(this.el) ? -1 : 1) * (scrollLeft / max);
5158

5259
this.ionSegmentViewScroll.emit({

core/src/components/segment-view/test/basic/segment-view.e2e.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,37 @@ configs({ modes: ['md'] }).forEach(({ title, config }) => {
128128
await expect(segmentButton).toHaveClass(/segment-button-checked/);
129129
});
130130

131+
test('should not emit ionSegmentViewScroll with NaN or Infinity scrollRatio when only one content item is present', async ({
132+
page,
133+
}) => {
134+
await page.setContent(
135+
`
136+
<ion-segment value="only">
137+
<ion-segment-button content-id="only" value="only">
138+
<ion-label>Only</ion-label>
139+
</ion-segment-button>
140+
</ion-segment>
141+
<ion-segment-view>
142+
<ion-segment-content id="only">Only</ion-segment-content>
143+
</ion-segment-view>
144+
`,
145+
config
146+
);
147+
148+
const ionSegmentViewScroll = await page.spyOnEvent('ionSegmentViewScroll');
149+
150+
// Programmatically dispatch a scroll event on the segment-view host element
151+
// to simulate what the browser fires when scrollLeft changes.
152+
await page.locator('ion-segment-view').evaluate((el: HTMLElement) => {
153+
el.dispatchEvent(new Event('scroll', { bubbles: true }));
154+
});
155+
156+
await page.waitForChanges();
157+
158+
// The max === 0 guard should prevent ionSegmentViewScroll from firing entirely.
159+
expect(ionSegmentViewScroll).not.toHaveReceivedEvent();
160+
});
161+
131162
test('should set correct segment button as checked and show correct content when programmatically setting the segment value', async ({
132163
page,
133164
}) => {

0 commit comments

Comments
 (0)