Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions core/src/components/segment-view/segment-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
31 changes: 31 additions & 0 deletions core/src/components/segment-view/test/basic/segment-view.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
`
<ion-segment value="only">
<ion-segment-button content-id="only" value="only">
<ion-label>Only</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment-view>
<ion-segment-content id="only">Only</ion-segment-content>
</ion-segment-view>
`,
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,
}) => {
Expand Down
1 change: 1 addition & 0 deletions core/src/components/segment/segment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading