@@ -63,6 +63,12 @@ export type ScrollDirection = 'after' | 'before';
63
63
*/
64
64
const EXAGGERATED_OVERSCROLL = 60 ;
65
65
66
+ /**
67
+ * The distance in pixels added on top of the scroll amount when using paginations to scroll a
68
+ * tab list. It is used to compensate for the padding on either side of a label.
69
+ */
70
+ const REDEEMING_OVERSCROLL = 24 ;
71
+
66
72
/**
67
73
* Amount of milliseconds to wait before starting to scroll the header automatically.
68
74
* Set a little conservatively in order to handle fake events dispatched on touch devices.
@@ -468,18 +474,37 @@ export abstract class MatPaginatedTabHeader
468
474
469
475
/**
470
476
* Moves the tab list in the 'before' or 'after' direction (towards the beginning of the list or
471
- * the end of the list, respectively). The distance to scroll is computed to be a third of the
472
- * length of the tab list view window.
477
+ * the end of the list, respectively). The distance to scroll is computed to be the smaller value
478
+ * between the remaining space to the (left/right) border and a third of the length of the tab
479
+ * list view window.
473
480
*
474
481
* This is an expensive call that forces a layout reflow to compute box and scroll metrics and
475
482
* should be called sparingly.
476
483
*/
477
484
_scrollHeader ( direction : ScrollDirection ) {
478
485
const viewLength = this . _tabListContainer . nativeElement . offsetWidth ;
479
486
480
- // Move the scroll distance one-third the length of the tab list's viewport.
481
- const scrollAmount = ( ( direction == 'before' ? - 1 : 1 ) * viewLength ) / 3 ;
487
+ // minLeftSpace: the distance from the first fully rendered label to the left border of the viewport.
488
+ // minRightSpace: the distance from the last fully rendered label to the right border of the viewport.
489
+ let minLeftSpace = Number . MAX_SAFE_INTEGER ;
490
+ let minRightSpace = Number . MAX_SAFE_INTEGER ;
491
+ this . _items . toArray ( ) . forEach ( tab => {
492
+ const { offsetLeft, offsetWidth} = tab . elementRef . nativeElement ;
493
+ const leftSpace = offsetLeft - this . scrollDistance + REDEEMING_OVERSCROLL ;
494
+ const rightSpace =
495
+ viewLength - ( offsetLeft + offsetWidth - this . scrollDistance ) + REDEEMING_OVERSCROLL ;
496
+ if ( leftSpace > 0 ) {
497
+ minLeftSpace = Math . min ( minLeftSpace , leftSpace ) ;
498
+ }
499
+ if ( rightSpace > 0 ) {
500
+ minRightSpace = Math . min ( minRightSpace , rightSpace ) ;
501
+ }
502
+ } ) ;
482
503
504
+ const scrollAmount =
505
+ direction == 'before'
506
+ ? - Math . min ( minRightSpace , viewLength / 3 )
507
+ : Math . min ( minLeftSpace , viewLength / 3 ) ;
483
508
return this . _scrollTo ( this . _scrollDistance + scrollAmount ) ;
484
509
}
485
510
0 commit comments