Skip to content

Commit

Permalink
fix(material/tabs): ensure the ink bar realigns when the tab header i…
Browse files Browse the repository at this point in the history
…tems have changed in dimensions
  • Loading branch information
hilts-vaughan committed May 13, 2022
1 parent a47869c commit 3dfef13
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
33 changes: 31 additions & 2 deletions src/material/tabs/paginated-tab-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {ViewportRuler} from '@angular/cdk/scrolling';
import {FocusKeyManager, FocusableOption} from '@angular/cdk/a11y';
import {ENTER, SPACE, hasModifierKey} from '@angular/cdk/keycodes';
import {merge, of as observableOf, Subject, timer, fromEvent} from 'rxjs';
import {take, takeUntil} from 'rxjs/operators';
import {take, map, startWith, takeUntil} from 'rxjs/operators';
import {Platform, normalizePassiveListenerOptions} from '@angular/cdk/platform';
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';

Expand Down Expand Up @@ -218,7 +218,7 @@ export abstract class MatPaginatedTabHeader

// On dir change or window resize, realign the ink bar and update the orientation of
// the key manager if the direction has changed.
merge(dirChange, resize, this._items.changes)
merge(dirChange, resize, this._getItemChanges())
.pipe(takeUntil(this._destroyed))
.subscribe(() => {
// We need to defer this to give the browser some time to recalculate
Expand Down Expand Up @@ -246,6 +246,35 @@ export abstract class MatPaginatedTabHeader
});
}

/** A method responsible for sending any change that could affect layout about
* items to subscribers.
*/
_getItemChanges() {
const itemContainerItemChanged = new Subject<void>();

// Check to see if ResizeObserver is supported and if not, stub the function
// out so that it does nothing if not supported
const observer =
typeof ResizeObserver === 'function'
? new ResizeObserver(() => {
itemContainerItemChanged.next();
})
: {
observe: () => {},
};

return merge(this._items.changes, itemContainerItemChanged).pipe(
startWith(this._items),
map(() => {
for (const item of this._items.toArray()) {
this._ngZone.runOutsideAngular(() => {
observer.observe(item.elementRef.nativeElement);
});
}
}),
);
}

ngAfterContentChecked(): void {
// If the number of tab labels have changed, check if scrolling should be enabled
if (this._tabLabelCount != this._items.length) {
Expand Down
17 changes: 17 additions & 0 deletions src/material/tabs/tab-header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,23 @@ describe('MatTabHeader', () => {
discardPeriodicTasks();
}));

it('should re-align the ink bar when the size of a tab changes', fakeAsync(() => {
fixture = TestBed.createComponent(SimpleTabHeaderApp);
fixture.detectChanges();

const inkBar = fixture.componentInstance.tabHeader._inkBar;

spyOn(inkBar, 'alignToElement');

// Change font-size which would trigger a container width change
(fixture.elementRef.nativeElement as HTMLElement).style.fontSize = '20px';
tick(150);
fixture.detectChanges();

expect(inkBar.alignToElement).toHaveBeenCalled();
discardPeriodicTasks();
}));

it('should update arrows when the window is resized', fakeAsync(() => {
fixture = TestBed.createComponent(SimpleTabHeaderApp);

Expand Down

0 comments on commit 3dfef13

Please sign in to comment.