Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(material/tabs): wrong scroll distance if selected tab is removed #24118

Merged
merged 1 commit into from Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/material-experimental/mdc-tabs/tab-header.spec.ts
Expand Up @@ -318,6 +318,28 @@ describe('MDC-based MatTabHeader', () => {
.withContext('Expected no ripple to show up after mousedown')
.toBe(0);
});

it('should update the scroll distance if a tab is removed and no tabs are selected', fakeAsync(() => {
appComponent.selectedIndex = 0;
appComponent.addTabsForScrolling();
fixture.detectChanges();

// Focus the last tab so the header scrolls to the end.
appComponent.tabHeader.focusIndex = appComponent.tabs.length - 1;
fixture.detectChanges();
expect(appComponent.tabHeader.scrollDistance).toBe(
appComponent.tabHeader._getMaxScrollDistance(),
);

// Remove the first two tabs which includes the selected tab.
appComponent.tabs = appComponent.tabs.slice(2);
fixture.detectChanges();
tick();

expect(appComponent.tabHeader.scrollDistance).toBe(
appComponent.tabHeader._getMaxScrollDistance(),
);
}));
});

describe('rtl', () => {
Expand Down
11 changes: 10 additions & 1 deletion src/material/tabs/paginated-tab-header.ts
Expand Up @@ -211,7 +211,16 @@ export abstract class MatPaginatedTabHeader
// We need to defer this to give the browser some time to recalculate
// the element dimensions. The call has to be wrapped in `NgZone.run`,
// because the viewport change handler runs outside of Angular.
this._ngZone.run(() => Promise.resolve().then(realign));
this._ngZone.run(() => {
Promise.resolve().then(() => {
// Clamp the scroll distance, because it can change with the number of tabs.
this._scrollDistance = Math.max(
0,
Math.min(this._getMaxScrollDistance(), this._scrollDistance),
);
realign();
});
});
this._keyManager.withHorizontalOrientation(this._getLayoutDirection());
});

Expand Down
22 changes: 22 additions & 0 deletions src/material/tabs/tab-header.spec.ts
Expand Up @@ -315,6 +315,28 @@ describe('MatTabHeader', () => {
.withContext('Expected no ripple to show up after mousedown')
.toBe(0);
});

it('should update the scroll distance if a tab is removed and no tabs are selected', fakeAsync(() => {
appComponent.selectedIndex = 0;
appComponent.addTabsForScrolling();
fixture.detectChanges();

// Focus the last tab so the header scrolls to the end.
appComponent.tabHeader.focusIndex = appComponent.tabs.length - 1;
fixture.detectChanges();
expect(appComponent.tabHeader.scrollDistance).toBe(
appComponent.tabHeader._getMaxScrollDistance(),
);

// Remove the first two tabs which includes the selected tab.
appComponent.tabs = appComponent.tabs.slice(2);
fixture.detectChanges();
tick();

expect(appComponent.tabHeader.scrollDistance).toBe(
appComponent.tabHeader._getMaxScrollDistance(),
);
}));
});

describe('rtl', () => {
Expand Down