fix(segment): clear transform styles on scroll end

This commit is contained in:
Tanner Reits
2024-09-27 18:27:32 -04:00
parent cbee05e488
commit 0a13ab449a
2 changed files with 45 additions and 21 deletions

View File

@@ -25,12 +25,20 @@ export class SegmentView implements ComponentInterface {
/**
* Emitted when the segment view is scrolled.
*/
@Event() ionSegmentViewScroll!: EventEmitter<{ scrollDirection: string; scrollDistancePercentage: number }>;
@Event() ionSegmentViewScroll!: EventEmitter<{
scrollDirection: string;
scrollDistance: number;
scrollDistancePercentage: number;
}>;
/**
* Emitted when the segment view scroll has ended.
*/
@Event() ionSegmentViewScrollEnd!: EventEmitter<void>;
@Event() ionSegmentViewScrollEnd!: EventEmitter<{ activeContentId: string }>;
@Event() ionSegmentViewScrollStart!: EventEmitter<void>;
private activeContentId = '';
@Listen('scroll')
handleScroll(ev: Event) {
@@ -53,6 +61,7 @@ export class SegmentView implements ComponentInterface {
// Emit the scroll direction and distance
this.ionSegmentViewScroll.emit({
scrollDirection,
scrollDistance,
scrollDistancePercentage,
});
@@ -67,12 +76,8 @@ export class SegmentView implements ComponentInterface {
return;
}
const segmentButton = this.getSegmentButtonById(segmentContent.id) as HTMLIonSegmentButtonElement;
const segment = this.getParentSegment(segmentButton);
if (segment) {
segment.value = segmentButton.value;
}
// Store the active `ion-segment-content` id so we can emit it when the scroll ends
this.activeContentId = segmentContent.id;
this.resetScrollEndTimeout();
}
@@ -82,6 +87,8 @@ export class SegmentView implements ComponentInterface {
*/
@Listen('touchstart')
handleScrollStart() {
this.ionSegmentViewScrollStart.emit();
if (this.scrollEndTimeout) {
clearTimeout(this.scrollEndTimeout);
this.scrollEndTimeout = null;
@@ -118,7 +125,7 @@ export class SegmentView implements ComponentInterface {
*/
private checkForScrollEnd() {
if (!this.isTouching) {
this.ionSegmentViewScrollEnd.emit();
this.ionSegmentViewScrollEnd.emit({ activeContentId: this.activeContentId });
this.initialScrollLeft = undefined;
}
}
@@ -149,14 +156,6 @@ export class SegmentView implements ComponentInterface {
return Array.from(this.el.querySelectorAll('ion-segment-content:not([disabled])'));
}
private getSegmentButtonById(id: string) {
return document.querySelector(`ion-segment-button[content-id="${id}"]`);
}
private getParentSegment(button: Element) {
return button.closest('ion-segment');
}
render() {
const { disabled } = this;

View File

@@ -28,6 +28,7 @@ export class Segment implements ComponentInterface {
private valueBeforeGesture?: SegmentValue;
private segmentViewEl?: HTMLIonSegmentViewElement | null = null;
private scrolledIndicator?: HTMLDivElement | null = null;
@Element() el!: HTMLIonSegmentElement;
@@ -87,7 +88,11 @@ export class Segment implements ComponentInterface {
const current = buttons.find((button) => button.value === value);
if (previous && current) {
this.checkButton(previous, current);
if (!this.segmentViewEl) {
this.checkButton(previous, current);
} else {
this.setCheckedClasses();
}
}
}
@@ -96,7 +101,11 @@ export class Segment implements ComponentInterface {
* Used by `ion-segment-button` to determine if the button should be checked.
*/
this.ionSelect.emit({ value });
this.scrollActiveButtonIntoView();
// The scroll listener should handle scrolling the active button into view as needed
if (!this.segmentViewEl) {
this.scrollActiveButtonIntoView();
}
}
/**
@@ -357,10 +366,13 @@ export class Segment implements ComponentInterface {
const index = buttons.findIndex((button) => button.value === this.value);
const current = buttons[index];
const indicatorEl = this.getIndicator(current);
this.scrolledIndicator = indicatorEl;
const { scrollDirection, scrollDistancePercentage } = ev.detail;
const { scrollDirection, scrollDistancePercentage, scrollDistance } = ev.detail;
if (indicatorEl) {
console.log('scroll', scrollDistancePercentage, scrollDistance);
if (indicatorEl && !isNaN(scrollDistancePercentage)) {
indicatorEl.style.transition = 'transform 0.3s ease-out';
const scrollDistance = scrollDistancePercentage * current.getBoundingClientRect().width;
@@ -390,6 +402,19 @@ export class Segment implements ComponentInterface {
}
}
@Listen('ionSegmentViewScrollStart', { target: 'body' })
onScrollStart() {}
@Listen('ionSegmentViewScrollEnd', { target: 'body' })
onScrollEnd(ev: CustomEvent<{ activeContentId: string }>) {
this.value = ev.detail.activeContentId;
if (this.scrolledIndicator) {
this.scrolledIndicator.style.transition = '';
this.scrolledIndicator.style.transform = '';
}
}
/**
* Finds the related segment view and sets its current content
* based on the selected segment button. This method