Skip to content

Commit 0a13ab4

Browse files
author
Tanner Reits
committed
fix(segment): clear transform styles on scroll end
1 parent cbee05e commit 0a13ab4

File tree

2 files changed

+45
-21
lines changed

2 files changed

+45
-21
lines changed

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

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,20 @@ export class SegmentView implements ComponentInterface {
2525
/**
2626
* Emitted when the segment view is scrolled.
2727
*/
28-
@Event() ionSegmentViewScroll!: EventEmitter<{ scrollDirection: string; scrollDistancePercentage: number }>;
28+
@Event() ionSegmentViewScroll!: EventEmitter<{
29+
scrollDirection: string;
30+
scrollDistance: number;
31+
scrollDistancePercentage: number;
32+
}>;
2933

3034
/**
3135
* Emitted when the segment view scroll has ended.
3236
*/
33-
@Event() ionSegmentViewScrollEnd!: EventEmitter<void>;
37+
@Event() ionSegmentViewScrollEnd!: EventEmitter<{ activeContentId: string }>;
38+
39+
@Event() ionSegmentViewScrollStart!: EventEmitter<void>;
40+
41+
private activeContentId = '';
3442

3543
@Listen('scroll')
3644
handleScroll(ev: Event) {
@@ -53,6 +61,7 @@ export class SegmentView implements ComponentInterface {
5361
// Emit the scroll direction and distance
5462
this.ionSegmentViewScroll.emit({
5563
scrollDirection,
64+
scrollDistance,
5665
scrollDistancePercentage,
5766
});
5867

@@ -67,12 +76,8 @@ export class SegmentView implements ComponentInterface {
6776
return;
6877
}
6978

70-
const segmentButton = this.getSegmentButtonById(segmentContent.id) as HTMLIonSegmentButtonElement;
71-
const segment = this.getParentSegment(segmentButton);
72-
73-
if (segment) {
74-
segment.value = segmentButton.value;
75-
}
79+
// Store the active `ion-segment-content` id so we can emit it when the scroll ends
80+
this.activeContentId = segmentContent.id;
7681

7782
this.resetScrollEndTimeout();
7883
}
@@ -82,6 +87,8 @@ export class SegmentView implements ComponentInterface {
8287
*/
8388
@Listen('touchstart')
8489
handleScrollStart() {
90+
this.ionSegmentViewScrollStart.emit();
91+
8592
if (this.scrollEndTimeout) {
8693
clearTimeout(this.scrollEndTimeout);
8794
this.scrollEndTimeout = null;
@@ -118,7 +125,7 @@ export class SegmentView implements ComponentInterface {
118125
*/
119126
private checkForScrollEnd() {
120127
if (!this.isTouching) {
121-
this.ionSegmentViewScrollEnd.emit();
128+
this.ionSegmentViewScrollEnd.emit({ activeContentId: this.activeContentId });
122129
this.initialScrollLeft = undefined;
123130
}
124131
}
@@ -149,14 +156,6 @@ export class SegmentView implements ComponentInterface {
149156
return Array.from(this.el.querySelectorAll('ion-segment-content:not([disabled])'));
150157
}
151158

152-
private getSegmentButtonById(id: string) {
153-
return document.querySelector(`ion-segment-button[content-id="${id}"]`);
154-
}
155-
156-
private getParentSegment(button: Element) {
157-
return button.closest('ion-segment');
158-
}
159-
160159
render() {
161160
const { disabled } = this;
162161

core/src/components/segment/segment.tsx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export class Segment implements ComponentInterface {
2828
private valueBeforeGesture?: SegmentValue;
2929

3030
private segmentViewEl?: HTMLIonSegmentViewElement | null = null;
31+
private scrolledIndicator?: HTMLDivElement | null = null;
3132

3233
@Element() el!: HTMLIonSegmentElement;
3334

@@ -87,7 +88,11 @@ export class Segment implements ComponentInterface {
8788
const current = buttons.find((button) => button.value === value);
8889

8990
if (previous && current) {
90-
this.checkButton(previous, current);
91+
if (!this.segmentViewEl) {
92+
this.checkButton(previous, current);
93+
} else {
94+
this.setCheckedClasses();
95+
}
9196
}
9297
}
9398

@@ -96,7 +101,11 @@ export class Segment implements ComponentInterface {
96101
* Used by `ion-segment-button` to determine if the button should be checked.
97102
*/
98103
this.ionSelect.emit({ value });
99-
this.scrollActiveButtonIntoView();
104+
105+
// The scroll listener should handle scrolling the active button into view as needed
106+
if (!this.segmentViewEl) {
107+
this.scrollActiveButtonIntoView();
108+
}
100109
}
101110

102111
/**
@@ -357,10 +366,13 @@ export class Segment implements ComponentInterface {
357366
const index = buttons.findIndex((button) => button.value === this.value);
358367
const current = buttons[index];
359368
const indicatorEl = this.getIndicator(current);
369+
this.scrolledIndicator = indicatorEl;
370+
371+
const { scrollDirection, scrollDistancePercentage, scrollDistance } = ev.detail;
360372

361-
const { scrollDirection, scrollDistancePercentage } = ev.detail;
373+
console.log('scroll', scrollDistancePercentage, scrollDistance);
362374

363-
if (indicatorEl) {
375+
if (indicatorEl && !isNaN(scrollDistancePercentage)) {
364376
indicatorEl.style.transition = 'transform 0.3s ease-out';
365377

366378
const scrollDistance = scrollDistancePercentage * current.getBoundingClientRect().width;
@@ -390,6 +402,19 @@ export class Segment implements ComponentInterface {
390402
}
391403
}
392404

405+
@Listen('ionSegmentViewScrollStart', { target: 'body' })
406+
onScrollStart() {}
407+
408+
@Listen('ionSegmentViewScrollEnd', { target: 'body' })
409+
onScrollEnd(ev: CustomEvent<{ activeContentId: string }>) {
410+
this.value = ev.detail.activeContentId;
411+
412+
if (this.scrolledIndicator) {
413+
this.scrolledIndicator.style.transition = '';
414+
this.scrolledIndicator.style.transform = '';
415+
}
416+
}
417+
393418
/**
394419
* Finds the related segment view and sets its current content
395420
* based on the selected segment button. This method

0 commit comments

Comments
 (0)