Skip to content

Commit 2f84389

Browse files
authored
feat(material-experimental/mdc-tabs): add default fitInkBarToContent option (#17556)
* feat(material-experimental/mdc-tabs): add default fitInkBarToContent option * fix indentation * add truthy check in tests * update goldens
1 parent 031e15f commit 2f84389

File tree

8 files changed

+119
-23
lines changed

8 files changed

+119
-23
lines changed

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {By} from '@angular/platform-browser';
66
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
77
import {CommonModule} from '@angular/common';
88
import {Observable} from 'rxjs';
9-
import {MatTab, MatTabGroup, MatTabHeaderPosition, MatTabsModule} from './index';
9+
import {MAT_TABS_CONFIG, MatTab, MatTabGroup, MatTabHeaderPosition, MatTabsModule} from './index';
1010

1111

1212
describe('MatTabGroup', () => {
@@ -698,6 +698,7 @@ describe('MatTabGroup with ink bar fit to content', () => {
698698
const tabElement = fixture.nativeElement.querySelector('.mdc-tab');
699699
const contentElement = tabElement.querySelector('.mdc-tab__content');
700700
const indicatorElement = tabElement.querySelector('.mdc-tab-indicator');
701+
expect(indicatorElement.parentElement).toBeTruthy();
701702
expect(indicatorElement.parentElement).toBe(contentElement);
702703
});
703704

@@ -707,12 +708,44 @@ describe('MatTabGroup with ink bar fit to content', () => {
707708

708709
const tabElement = fixture.nativeElement.querySelector('.mdc-tab');
709710
const indicatorElement = tabElement.querySelector('.mdc-tab-indicator');
711+
expect(indicatorElement.parentElement).toBeTruthy();
710712
expect(indicatorElement.parentElement).toBe(tabElement);
711713

712714
fixture.componentInstance.fitInkBarToContent = true;
713715
fixture.detectChanges();
714716

715717
const contentElement = tabElement.querySelector('.mdc-tab__content');
718+
expect(indicatorElement.parentElement).toBeTruthy();
719+
expect(indicatorElement.parentElement).toBe(contentElement);
720+
});
721+
});
722+
723+
724+
describe('MatTabNavBar with a default config', () => {
725+
let fixture: ComponentFixture<SimpleTabsTestApp>;
726+
727+
beforeEach(fakeAsync(() => {
728+
TestBed.configureTestingModule({
729+
imports: [MatTabsModule, BrowserAnimationsModule],
730+
declarations: [SimpleTabsTestApp],
731+
providers: [
732+
{provide: MAT_TABS_CONFIG, useValue: {fitInkBarToContent: true}}
733+
]
734+
});
735+
736+
TestBed.compileComponents();
737+
}));
738+
739+
beforeEach(() => {
740+
fixture = TestBed.createComponent(SimpleTabsTestApp);
741+
fixture.detectChanges();
742+
});
743+
744+
it('should set whether the ink bar fits to content', () => {
745+
const tabElement = fixture.nativeElement.querySelector('.mdc-tab');
746+
const contentElement = tabElement.querySelector('.mdc-tab__content');
747+
const indicatorElement = tabElement.querySelector('.mdc-tab-indicator');
748+
expect(indicatorElement.parentElement).toBeTruthy();
716749
expect(indicatorElement.parentElement).toBe(contentElement);
717750
});
718751
});

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ export class MatTabGroup extends _MatTabGroupBase {
7070
@Inject(MAT_TABS_CONFIG) @Optional() defaultConfig?: MatTabsConfig,
7171
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string) {
7272
super(elementRef, changeDetectorRef, defaultConfig, animationMode);
73+
this.fitInkBarToContent = defaultConfig && defaultConfig.fitInkBarToContent != null ?
74+
defaultConfig.fitInkBarToContent : false;
7375
}
7476

7577
static ngAcceptInputType_fitInkBarToContent: boolean | string;

src/material-experimental/mdc-tabs/tab-nav-bar/tab-nav-bar.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {Direction, Directionality} from '@angular/cdk/bidi';
77
import {Subject} from 'rxjs';
88
import {MatTabsModule} from '../module';
99
import {MatTabLink, MatTabNav} from './tab-nav-bar';
10+
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
11+
import {MAT_TABS_CONFIG} from '../index';
1012

1113

1214
describe('MatTabNavBar', () => {
@@ -335,6 +337,7 @@ describe('MatTabNavBar', () => {
335337
const tabElement = fixture.nativeElement.querySelector('.mdc-tab');
336338
const contentElement = tabElement.querySelector('.mdc-tab__content');
337339
const indicatorElement = tabElement.querySelector('.mdc-tab-indicator');
340+
expect(indicatorElement.parentElement).toBeTruthy();
338341
expect(indicatorElement.parentElement).toBe(contentElement);
339342
});
340343

@@ -344,17 +347,49 @@ describe('MatTabNavBar', () => {
344347

345348
const tabElement = fixture.nativeElement.querySelector('.mdc-tab');
346349
const indicatorElement = tabElement.querySelector('.mdc-tab-indicator');
350+
expect(indicatorElement.parentElement).toBeTruthy();
347351
expect(indicatorElement.parentElement).toBe(tabElement);
348352

349353
fixture.componentInstance.fitInkBarToContent = true;
350354
fixture.detectChanges();
351355

352356
const contentElement = tabElement.querySelector('.mdc-tab__content');
357+
expect(indicatorElement.parentElement).toBeTruthy();
353358
expect(indicatorElement.parentElement).toBe(contentElement);
354359
});
355360
});
356361
});
357362

363+
describe('MatTabNavBar with a default config', () => {
364+
let fixture: ComponentFixture<TabLinkWithTabIndexBinding>;
365+
366+
beforeEach(fakeAsync(() => {
367+
TestBed.configureTestingModule({
368+
imports: [MatTabsModule, BrowserAnimationsModule],
369+
declarations: [TabLinkWithTabIndexBinding],
370+
providers: [
371+
{provide: MAT_TABS_CONFIG, useValue: {fitInkBarToContent: true}}
372+
]
373+
});
374+
375+
TestBed.compileComponents();
376+
}));
377+
378+
beforeEach(() => {
379+
fixture = TestBed.createComponent(TabLinkWithTabIndexBinding);
380+
fixture.detectChanges();
381+
});
382+
383+
it('should set whether the ink bar fits to content', () => {
384+
const tabElement = fixture.nativeElement.querySelector('.mdc-tab');
385+
const contentElement = tabElement.querySelector('.mdc-tab__content');
386+
const indicatorElement = tabElement.querySelector('.mdc-tab-indicator');
387+
expect(indicatorElement.parentElement).toBeTruthy();
388+
expect(indicatorElement.parentElement).toBe(contentElement);
389+
});
390+
});
391+
392+
358393
@Component({
359394
selector: 'test-app',
360395
template: `

src/material-experimental/mdc-tabs/tab-nav-bar/tab-nav-bar.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ import {
2525
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
2626
import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core';
2727
import {FocusMonitor} from '@angular/cdk/a11y';
28-
import {_MatTabNavBase, _MatTabLinkBase} from '@angular/material/tabs';
28+
import {
29+
_MatTabNavBase,
30+
_MatTabLinkBase,
31+
MAT_TABS_CONFIG,
32+
MatTabsConfig
33+
} from '@angular/material/tabs';
2934
import {DOCUMENT} from '@angular/common';
3035
import {Directionality} from '@angular/cdk/bidi';
3136
import {ViewportRuler} from '@angular/cdk/scrolling';
@@ -81,8 +86,13 @@ export class MatTabNav extends _MatTabNavBase implements AfterContentInit {
8186
* @deprecated @breaking-change 9.0.0 `platform` parameter to become required.
8287
*/
8388
@Optional() platform?: Platform,
84-
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string) {
89+
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
90+
@Optional() @Inject(MAT_TABS_CONFIG) defaultConfig?: MatTabsConfig) {
8591
super(elementRef, dir, ngZone, changeDetectorRef, viewportRuler, platform, animationMode);
92+
this.disablePagination = defaultConfig && defaultConfig.disablePagination != null ?
93+
defaultConfig.disablePagination : false;
94+
this.fitInkBarToContent = defaultConfig && defaultConfig.fitInkBarToContent != null ?
95+
defaultConfig.fitInkBarToContent : false;
8696
}
8797

8898
ngAfterContentInit() {

src/material/tabs/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ export {MatTabNav, MatTabLink, _MatTabNavBase, _MatTabLinkBase} from './tab-nav-
2424
export {MatTabContent} from './tab-content';
2525
export {ScrollDirection} from './paginated-tab-header';
2626
export * from './tabs-animations';
27+
export {MAT_TABS_CONFIG, MatTabsConfig} from './tab-config';

src/material/tabs/tab-config.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import {InjectionToken} from '@angular/core';
9+
10+
/** Object that can be used to configure the default options for the tabs module. */
11+
export interface MatTabsConfig {
12+
/** Duration for the tab animation. Must be a valid CSS value (e.g. 600ms). */
13+
animationDuration?: string;
14+
15+
/**
16+
* Whether pagination should be disabled. This can be used to avoid unnecessary
17+
* layout recalculations if it's known that pagination won't be required.
18+
*/
19+
disablePagination?: boolean;
20+
21+
/**
22+
* Whether the ink bar should fit its width to the size of the tab label content.
23+
* This only applies to the MDC-based tabs.
24+
*/
25+
fitInkBarToContent?: boolean;
26+
}
27+
28+
/** Injection token that can be used to provide the default options the tabs module. */
29+
export const MAT_TABS_CONFIG = new InjectionToken<MatTabsConfig>('MAT_TABS_CONFIG');

src/material/tabs/tab-group.ts

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,17 @@ import {
1414
ChangeDetectorRef,
1515
Component,
1616
ContentChildren,
17+
Directive,
1718
ElementRef,
1819
EventEmitter,
20+
Inject,
1921
Input,
2022
OnDestroy,
23+
Optional,
2124
Output,
2225
QueryList,
2326
ViewChild,
2427
ViewEncapsulation,
25-
Optional,
26-
Inject,
27-
InjectionToken,
28-
Directive,
2928
} from '@angular/core';
3029
import {
3130
CanColor,
@@ -39,7 +38,8 @@ import {
3938
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
4039
import {merge, Subscription} from 'rxjs';
4140
import {startWith} from 'rxjs/operators';
42-
import {MatTab, MAT_TAB_GROUP} from './tab';
41+
import {MAT_TAB_GROUP, MatTab} from './tab';
42+
import {MAT_TABS_CONFIG, MatTabsConfig} from './tab-config';
4343

4444

4545
/** Used to generate unique ID's for each tab component */
@@ -56,21 +56,6 @@ export class MatTabChangeEvent {
5656
/** Possible positions for the tab header. */
5757
export type MatTabHeaderPosition = 'above' | 'below';
5858

59-
/** Object that can be used to configure the default options for the tabs module. */
60-
export interface MatTabsConfig {
61-
/** Duration for the tab animation. Must be a valid CSS value (e.g. 600ms). */
62-
animationDuration?: string;
63-
64-
/**
65-
* Whether pagination should be disabled. This can be used to avoid unnecessary
66-
* layout recalculations if it's known that pagination won't be required.
67-
*/
68-
disablePagination?: boolean;
69-
}
70-
71-
/** Injection token that can be used to provide the default options the tabs module. */
72-
export const MAT_TABS_CONFIG = new InjectionToken<MatTabsConfig>('MAT_TABS_CONFIG');
73-
7459
// Boilerplate for applying mixins to MatTabGroup.
7560
/** @docs-private */
7661
class MatTabGroupMixinBase {

tools/public_api_guard/material/tabs.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ export declare const matTabsAnimations: {
211211
export interface MatTabsConfig {
212212
animationDuration?: string;
213213
disablePagination?: boolean;
214+
fitInkBarToContent?: boolean;
214215
}
215216

216217
export declare class MatTabsModule {

0 commit comments

Comments
 (0)