Skip to content

Commit

Permalink
fix(material/tabs): avoid pagination infinite loop in safari (#29121)
Browse files Browse the repository at this point in the history
Fixes a bug reported internally where the tabs pagination was going into an infinite loop at some widths.

The root cause is a bit unclear, but it looks like in some cases Safari rounds up the `scrollWidth` and in some it doesn't which we end up hitting when adding/removing the pagination.

These changes work around it by adding a 5px threshold that needs to be crossed before we start showing the pagination. The threshold shouldn't be noticable for users since the tabs have a 24px padding on each side.

(cherry picked from commit cc00a74)
  • Loading branch information
crisbeto committed May 28, 2024
1 parent d96b5e3 commit 2110f2c
Showing 1 changed file with 13 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/material/tabs/paginated-tab-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,18 +550,27 @@ export abstract class MatPaginatedTabHeader
if (this.disablePagination) {
this._showPaginationControls = false;
} else {
const isEnabled =
this._tabListInner.nativeElement.scrollWidth > this._elementRef.nativeElement.offsetWidth;
const scrollWidth = this._tabListInner.nativeElement.scrollWidth;
const containerWidth = this._elementRef.nativeElement.offsetWidth;

// Usually checking that the scroll width is greater than the container width should be
// enough, but on Safari at specific widths the browser ends up rounding up when there's
// no pagination and rounding down once the pagination is added. This can throw the component
// into an infinite loop where the pagination shows up and disappears constantly. We work
// around it by adding a threshold to the calculation. From manual testing the threshold
// can be lowered to 2px and still resolve the issue, but we set a higher one to be safe.
// This shouldn't cause any content to be clipped, because tabs have a 24px horizontal
// padding. See b/316395154 for more information.
const isEnabled = scrollWidth - containerWidth >= 5;

if (!isEnabled) {
this.scrollDistance = 0;
}

if (isEnabled !== this._showPaginationControls) {
this._showPaginationControls = isEnabled;
this._changeDetectorRef.markForCheck();
}

this._showPaginationControls = isEnabled;
}
}

Expand Down

0 comments on commit 2110f2c

Please sign in to comment.