Skip to content

Commit 7f556b5

Browse files
ukrukargandrewseguin
authored andcommitted
fix(material/tabs): stop scrolling on tab change (#22265)
* fix(material/tabs): stop scrolling on tab change Adds min-height to the mat-tab-group wrapper, so page height is preserved as tabs change, and page doesn't scroll up. Fixes #9592 * fix(material/tabs): stop scrolling on tab change Adds min-height to the mat-tab-group wrapper, so page height is preserved as tabs change, and page doesn't scroll up. Fixes #9592 * fix(material/tabs): stop scrolling on tab change … Adds min-height to the mat-tab-group wrapper, so page height is preserved as tabs change, and page doesn't scroll up. Fixes #9592 (cherry picked from commit c12f168)
1 parent 9bb7b0c commit 7f556b5

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

src/material-experimental/mdc-tabs/tab-group.spec.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ describe('MDC-based MatTabGroup', () => {
3232
TabGroupWithIsActiveBinding,
3333
NestedTabs,
3434
TabGroupWithIndirectDescendantTabs,
35+
TabGroupWithSpaceAbove,
3536
],
3637
});
3738

@@ -665,6 +666,45 @@ describe('MDC-based MatTabGroup', () => {
665666
}));
666667
});
667668

669+
describe('tall tabs', () => {
670+
beforeEach(() => {
671+
window.scrollTo({top: 0});
672+
});
673+
674+
it('should not scroll when changing tabs by clicking', fakeAsync(() => {
675+
const fixture = TestBed.createComponent(TabGroupWithSpaceAbove);
676+
fixture.detectChanges();
677+
tick();
678+
fixture.detectChanges();
679+
680+
window.scrollBy(0, 250);
681+
expect(window.scrollY).toBe(250);
682+
683+
// select the second tab
684+
let tabLabel = fixture.debugElement.queryAll(By.css('.mat-mdc-tab'))[1];
685+
tabLabel.nativeElement.click();
686+
checkSelectedIndex(1, fixture);
687+
688+
expect(window.scrollY).toBe(250);
689+
tick();
690+
}));
691+
692+
it('should not scroll when changing tabs programatically', fakeAsync(() => {
693+
const fixture = TestBed.createComponent(TabGroupWithSpaceAbove);
694+
fixture.detectChanges();
695+
tick();
696+
fixture.detectChanges();
697+
698+
window.scrollBy(0, 250);
699+
expect(window.scrollY).toBe(250);
700+
701+
fixture.componentInstance.tabGroup.selectedIndex = 1;
702+
fixture.detectChanges();
703+
704+
expect(window.scrollY).toBe(250);
705+
tick();
706+
}));
707+
});
668708

669709
/**
670710
* Checks that the `selectedIndex` has been updated; checks that the label and body have their
@@ -1067,3 +1107,24 @@ class TabGroupWithIndirectDescendantTabs {
10671107
class TabGroupWithInkBarFitToContent {
10681108
fitInkBarToContent = true;
10691109
}
1110+
1111+
@Component({
1112+
template: `
1113+
<div style="height: 300px; background-color: aqua">
1114+
Top Content here
1115+
</div>
1116+
<mat-tab-group>
1117+
<ng-container>
1118+
<mat-tab label="One">
1119+
<div style="height: 3000px; background-color: red"></div>
1120+
</mat-tab>
1121+
<mat-tab label="Two">
1122+
<div style="height: 3000px; background-color: green"></div>
1123+
</mat-tab>
1124+
</ng-container>
1125+
</mat-tab-group>
1126+
`,
1127+
})
1128+
class TabGroupWithSpaceAbove {
1129+
@ViewChild(MatTabGroup) tabGroup: MatTabGroup;
1130+
}

src/material/tabs/tab-group.spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ describe('MatTabGroup', () => {
3232
TabGroupWithIsActiveBinding,
3333
NestedTabs,
3434
TabGroupWithIndirectDescendantTabs,
35+
TabGroupWithSpaceAbove,
3536
],
3637
});
3738

@@ -664,6 +665,46 @@ describe('MatTabGroup', () => {
664665
}));
665666
});
666667

668+
describe('tall tabs', () => {
669+
beforeEach(() => {
670+
window.scrollTo({top: 0});
671+
});
672+
673+
it('should not scroll when changing tabs by clicking', fakeAsync(() => {
674+
const fixture = TestBed.createComponent(TabGroupWithSpaceAbove);
675+
fixture.detectChanges();
676+
tick();
677+
fixture.detectChanges();
678+
679+
window.scrollBy(0, 250);
680+
expect(window.scrollY).toBe(250);
681+
682+
// select the second tab
683+
let tabLabel = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
684+
tabLabel.nativeElement.click();
685+
checkSelectedIndex(1, fixture);
686+
687+
expect(window.scrollY).toBe(250);
688+
tick();
689+
}));
690+
691+
it('should not scroll when changing tabs programatically', fakeAsync(() => {
692+
const fixture = TestBed.createComponent(TabGroupWithSpaceAbove);
693+
fixture.detectChanges();
694+
tick();
695+
fixture.detectChanges();
696+
697+
window.scrollBy(0, 250);
698+
expect(window.scrollY).toBe(250);
699+
700+
fixture.componentInstance.tabGroup.selectedIndex = 1;
701+
fixture.detectChanges();
702+
703+
expect(window.scrollY).toBe(250);
704+
tick();
705+
}));
706+
});
707+
667708
/**
668709
* Checks that the `selectedIndex` has been updated; checks that the label and body have their
669710
* respective `active` classes
@@ -998,3 +1039,24 @@ class TabsWithCustomAnimationDuration {}
9981039
class TabGroupWithIndirectDescendantTabs {
9991040
@ViewChild(MatTabGroup) tabGroup: MatTabGroup;
10001041
}
1042+
1043+
@Component({
1044+
template: `
1045+
<div style="height: 300px; background-color: aqua">
1046+
Top Content here
1047+
</div>
1048+
<mat-tab-group>
1049+
<ng-container>
1050+
<mat-tab label="One">
1051+
<div style="height: 3000px; background-color: red"></div>
1052+
</mat-tab>
1053+
<mat-tab label="Two">
1054+
<div style="height: 3000px; background-color: green"></div>
1055+
</mat-tab>
1056+
</ng-container>
1057+
</mat-tab-group>
1058+
`,
1059+
})
1060+
class TabGroupWithSpaceAbove {
1061+
@ViewChild(MatTabGroup) tabGroup: MatTabGroup;
1062+
}

src/material/tabs/tab-group.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ export abstract class _MatTabGroupBase extends _MatTabGroupMixinBase implements
202202

203203
if (!isFirstRun) {
204204
this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));
205+
// Preserve the height so page doesn't scroll up during tab change.
206+
// Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change
207+
const wrapper = this._tabBodyWrapper.nativeElement;
208+
wrapper.style.minHeight = wrapper.clientHeight + 'px';
205209
}
206210

207211
// Changing these values after change detection has run
@@ -211,6 +215,9 @@ export abstract class _MatTabGroupBase extends _MatTabGroupMixinBase implements
211215

212216
if (!isFirstRun) {
213217
this.selectedIndexChange.emit(indexToSelect);
218+
// Clear the min-height, this was needed during tab change to avoid
219+
// unnecessary scrolling.
220+
this._tabBodyWrapper.nativeElement.style.minHeight = '';
214221
}
215222
});
216223
}

0 commit comments

Comments
 (0)