diff --git a/src/material/tabs/_tabs-common.scss b/src/material/tabs/_tabs-common.scss
index f22b4580eca2..15c36eb4326e 100644
--- a/src/material/tabs/_tabs-common.scss
+++ b/src/material/tabs/_tabs-common.scss
@@ -217,6 +217,10 @@ $mat-tab-animation-duration: 500ms !default;
tokens-mat-tab-header.$prefix, tokens-mat-tab-header.get-unthemable-tokens());
}
+ .mdc-tab-indicator .mdc-tab-indicator__content {
+ transition-duration: var(--mat-tab-animation-duration, 250ms);
+ }
+
.mat-mdc-tab-header-pagination {
@include vendor-prefixes.user-select(none);
position: relative;
diff --git a/src/material/tabs/tab-group.spec.ts b/src/material/tabs/tab-group.spec.ts
index 371232caf531..0b092d81f4b7 100644
--- a/src/material/tabs/tab-group.spec.ts
+++ b/src/material/tabs/tab-group.spec.ts
@@ -999,6 +999,15 @@ describe('nested MatTabGroup with enabled animations', () => {
tick();
}).not.toThrow();
}));
+
+ it('should set appropiate css variable given a specified animationDuration', fakeAsync(() => {
+ let fixture = TestBed.createComponent(TabsWithCustomAnimationDuration);
+ fixture.detectChanges();
+ tick();
+
+ const tabGroup = fixture.nativeElement.querySelector('.mat-mdc-tab-group');
+ expect(tabGroup.style.getPropertyValue('--mat-tab-animation-duration')).toBe('500ms');
+ }));
});
describe('MatTabGroup with ink bar fit to content', () => {
diff --git a/src/material/tabs/tab-group.ts b/src/material/tabs/tab-group.ts
index 4157bf08ab14..fc3e775910a1 100644
--- a/src/material/tabs/tab-group.ts
+++ b/src/material/tabs/tab-group.ts
@@ -528,6 +528,7 @@ export abstract class _MatTabGroupBase
'[class.mat-mdc-tab-group-dynamic-height]': 'dynamicHeight',
'[class.mat-mdc-tab-group-inverted-header]': 'headerPosition === "below"',
'[class.mat-mdc-tab-group-stretch-tabs]': 'stretchTabs',
+ '[style.--mat-tab-animation-duration]': 'animationDuration',
},
})
export class MatTabGroup extends _MatTabGroupBase {
diff --git a/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts b/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts
index 0dbc5dbb894c..d30951ef920f 100644
--- a/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts
+++ b/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts
@@ -489,6 +489,34 @@ describe('MatTabNavBar with a default config', () => {
});
});
+describe('MatTabNavBar with enabled animations', () => {
+ beforeEach(fakeAsync(() => {
+ TestBed.configureTestingModule({
+ imports: [MatTabsModule, BrowserAnimationsModule],
+ declarations: [TabsWithCustomAnimationDuration],
+ });
+
+ TestBed.compileComponents();
+ }));
+
+ it('should not throw when setting an animationDuration without units', fakeAsync(() => {
+ expect(() => {
+ let fixture = TestBed.createComponent(TabsWithCustomAnimationDuration);
+ fixture.detectChanges();
+ tick();
+ }).not.toThrow();
+ }));
+
+ it('should set appropiate css variable given a specified animationDuration', fakeAsync(() => {
+ let fixture = TestBed.createComponent(TabsWithCustomAnimationDuration);
+ fixture.detectChanges();
+ tick();
+
+ const tabNavBar = fixture.nativeElement.querySelector('.mat-mdc-tab-nav-bar');
+ expect(tabNavBar.style.getPropertyValue('--mat-tab-animation-duration')).toBe('500ms');
+ }));
+});
+
@Component({
selector: 'test-app',
template: `
@@ -545,3 +573,15 @@ class TabLinkWithNgIf {
class TabBarWithInactiveTabsOnInit {
tabs = [0, 1, 2];
}
+
+@Component({
+ template: `
+
+ ,
+ `,
+})
+class TabsWithCustomAnimationDuration {
+ links = ['First', 'Second', 'Third'];
+}
diff --git a/src/material/tabs/tab-nav-bar/tab-nav-bar.ts b/src/material/tabs/tab-nav-bar/tab-nav-bar.ts
index f48df15ea368..6ec9ca681b1e 100644
--- a/src/material/tabs/tab-nav-bar/tab-nav-bar.ts
+++ b/src/material/tabs/tab-nav-bar/tab-nav-bar.ts
@@ -45,7 +45,7 @@ import {Directionality} from '@angular/cdk/bidi';
import {ViewportRuler} from '@angular/cdk/scrolling';
import {Platform} from '@angular/cdk/platform';
import {MatInkBar, MatInkBarItem, mixinInkBarItem} from '../ink-bar';
-import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
+import {BooleanInput, coerceBooleanProperty, NumberInput} from '@angular/cdk/coercion';
import {BehaviorSubject, Subject} from 'rxjs';
import {startWith, takeUntil} from 'rxjs/operators';
import {SPACE} from '@angular/cdk/keycodes';
@@ -319,6 +319,7 @@ const _MatTabLinkBaseWithInkBarItem = mixinInkBarItem(_MatTabLinkBase);
'[class.mat-accent]': 'color === "accent"',
'[class.mat-warn]': 'color === "warn"',
'[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
+ '[style.--mat-tab-animation-duration]': 'animationDuration',
},
encapsulation: ViewEncapsulation.None,
// tslint:disable-next-line:validate-decorators
@@ -346,6 +347,17 @@ export class MatTabNav extends _MatTabNavBase implements AfterContentInit, After
}
private _stretchTabs = true;
+ @Input()
+ get animationDuration(): string {
+ return this._animationDuration;
+ }
+
+ set animationDuration(value: NumberInput) {
+ this._animationDuration = /^\d+$/.test(value + '') ? value + 'ms' : (value as string);
+ }
+
+ private _animationDuration: string;
+
@ContentChildren(forwardRef(() => MatTabLink), {descendants: true}) _items: QueryList;
@ViewChild('tabListContainer', {static: true}) _tabListContainer: ElementRef;
@ViewChild('tabList', {static: true}) _tabList: ElementRef;
diff --git a/tools/public_api_guard/material/tabs.md b/tools/public_api_guard/material/tabs.md
index 527854e2cb43..f11a43b522c0 100644
--- a/tools/public_api_guard/material/tabs.md
+++ b/tools/public_api_guard/material/tabs.md
@@ -489,6 +489,9 @@ export class _MatTabLinkBase extends _MatTabLinkMixinBase implements AfterViewIn
// @public
export class MatTabNav extends _MatTabNavBase implements AfterContentInit, AfterViewInit {
constructor(elementRef: ElementRef, dir: Directionality, ngZone: NgZone, changeDetectorRef: ChangeDetectorRef, viewportRuler: ViewportRuler, platform: Platform, animationMode?: string, defaultConfig?: MatTabsConfig);
+ // (undocumented)
+ get animationDuration(): string;
+ set animationDuration(value: NumberInput);
get fitInkBarToContent(): boolean;
set fitInkBarToContent(v: BooleanInput);
// (undocumented)
@@ -514,7 +517,7 @@ export class MatTabNav extends _MatTabNavBase implements AfterContentInit, After
// (undocumented)
_tabListInner: ElementRef;
// (undocumented)
- static ɵcmp: i0.ɵɵComponentDeclaration;
+ static ɵcmp: i0.ɵɵComponentDeclaration;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration;
}