Skip to content

Commit 374aaff

Browse files
willshowellkara
authored andcommitted
feat(tabs): add theming and ability to set background color (angular#5287)
1 parent e8005ec commit 374aaff

File tree

6 files changed

+175
-21
lines changed

6 files changed

+175
-21
lines changed

src/demo-app/tabs/tabs-demo.html

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ <h1>Tab Nav Bar</h1>
33
<button md-button (click)="tabLinks.shift()">Remove tab</button>
44
<button md-button (click)="swapTabLinks()">Swap first two</button>
55
<button md-button (click)="addToLabel()">Add to labels</button>
6+
<button md-button (click)="toggleBackground()">Toggle background</button>
67

78
<div class="demo-nav-bar">
8-
<nav md-tab-nav-bar aria-label="weather navigation links">
9+
<nav md-tab-nav-bar aria-label="weather navigation links" [backgroundColor]="tabNavBackground">
910
<a md-tab-link
1011
*ngFor="let tabLink of tabLinks; let i = index"
1112
[routerLink]="tabLink.link"
@@ -248,3 +249,31 @@ <h1>Inverted tabs</h1>
248249
</div>
249250
</md-tab>
250251
</md-tab-group>
252+
253+
<h1>Accent tabs</h1>
254+
<md-tab-group class="demo-tab-group" color="accent">
255+
<md-tab label="Earth">
256+
<div class="tab-content">
257+
This tab is about the Earth!
258+
</div>
259+
</md-tab>
260+
<md-tab label="Fire">
261+
<div class="tab-content">
262+
This tab is about combustion!
263+
</div>
264+
</md-tab>
265+
</md-tab-group>
266+
267+
<h1>Tabs with background color</h1>
268+
<md-tab-group class="demo-tab-group" backgroundColor="primary" color="accent">
269+
<md-tab label="Earth">
270+
<div class="tab-content">
271+
This tab is about the Earth!
272+
</div>
273+
</md-tab>
274+
<md-tab label="Fire">
275+
<div class="tab-content">
276+
This tab is about combustion!
277+
</div>
278+
</md-tab>
279+
</md-tab-group>

src/demo-app/tabs/tabs-demo.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export class TabsDemo {
1616
{label: 'Fog', link: 'foggy-tab'},
1717
];
1818

19+
tabNavBackground: any = undefined;
20+
1921
// Standard tabs demo
2022
tabs = [
2123
{
@@ -93,6 +95,10 @@ export class TabsDemo {
9395
addToLabel() {
9496
this.tabLinks.forEach(link => link.label += 'extracontent');
9597
}
98+
99+
toggleBackground() {
100+
this.tabNavBackground = this.tabNavBackground ? undefined : 'primary';
101+
}
96102
}
97103

98104

src/lib/tabs/_tabs-theme.scss

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,94 @@
2323
}
2424
}
2525

26-
.mat-tab-label:focus {
27-
background-color: mat-color($primary, lighter, 0.3);
26+
.mat-tab-label, .mat-tab-link {
27+
color: mat-color($foreground, text);
28+
29+
&.mat-tab-disabled {
30+
color: mat-color($foreground, disabled-text);
31+
}
32+
}
33+
34+
.mat-tab-header-pagination-chevron {
35+
border-color: mat-color($foreground, text);
36+
}
37+
38+
.mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron {
39+
border-color: mat-color($foreground, disabled-text);
40+
}
41+
42+
// Remove header border when there is a background color
43+
.mat-tab-group[class*='mat-background-'] .mat-tab-header,
44+
.mat-tab-nav-bar[class*='mat-background-'] {
45+
border-bottom: none;
46+
border-top: none;
47+
}
48+
49+
.mat-tab-group, .mat-tab-nav-bar {
50+
$theme-colors: (
51+
primary: $primary,
52+
accent: $accent,
53+
warn: $warn
54+
);
55+
56+
@each $name, $color in $theme-colors {
57+
// Set the foreground color of the tabs
58+
&.mat-#{$name} {
59+
@include _mat-tab-label-focus($color);
60+
@include _mat-ink-bar($color);
61+
62+
// Override ink bar when background color is the same
63+
&.mat-background-#{$name} {
64+
@include _mat-ink-bar($color, default-contrast);
65+
}
66+
}
67+
}
68+
69+
@each $name, $color in $theme-colors {
70+
// Set background color of the tabs and override focus color
71+
&.mat-background-#{$name} {
72+
@include _mat-tab-label-focus($color);
73+
@include _mat-tabs-background($color);
74+
}
75+
}
2876
}
77+
}
2978

79+
@mixin _mat-ink-bar($color, $hue: default) {
3080
.mat-ink-bar {
31-
background-color: mat-color($primary);
81+
background-color: mat-color($color, $hue);
82+
}
83+
}
84+
85+
@mixin _mat-tab-label-focus($tab-focus-color) {
86+
.mat-tab-label:focus, .mat-tab-link:focus {
87+
background-color: mat-color($tab-focus-color, lighter, 0.3);
88+
}
89+
}
90+
91+
@mixin _mat-tabs-background($background-color) {
92+
// Set background color for the tab group
93+
.mat-tab-header, .mat-tab-links {
94+
background-color: mat-color($background-color);
3295
}
3396

97+
// Set labels to contrast against background
3498
.mat-tab-label, .mat-tab-link {
35-
color: mat-color($foreground, text);
99+
color: mat-color($background-color, default-contrast);
36100

37101
&.mat-tab-disabled {
38-
color: mat-color($foreground, disabled-text);
102+
color: mat-color($background-color, default-contrast, 0.4);
39103
}
40104
}
105+
106+
// Set pagination chevrons to contrast background
107+
.mat-tab-header-pagination-chevron {
108+
border-color: mat-color($background-color, default-contrast);
109+
}
110+
111+
.mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron {
112+
border-color: mat-color($background-color, default-contrast, 0.4);
113+
}
41114
}
42115

43116
@mixin mat-tabs-typography($config) {

src/lib/tabs/tab-group.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {MdTab} from './tab';
3030
import {map} from '../core/rxjs/index';
3131
import {merge} from 'rxjs/observable/merge';
3232
import {CanDisableRipple, mixinDisableRipple} from '../core/common-behaviors/disable-ripple';
33+
import {CanColor, mixinColor, ThemePalette} from '../core/common-behaviors/color';
3334

3435

3536
/** Used to generate unique ID's for each tab component */
@@ -46,8 +47,10 @@ export type MdTabHeaderPosition = 'above' | 'below';
4647

4748
// Boilerplate for applying mixins to MdTabGroup.
4849
/** @docs-private */
49-
export class MdTabGroupBase {}
50-
export const _MdTabGroupMixinBase = mixinDisableRipple(MdTabGroupBase);
50+
export class MdTabGroupBase {
51+
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
52+
}
53+
export const _MdTabGroupMixinBase = mixinColor(mixinDisableRipple(MdTabGroupBase), 'primary');
5154

5255
/**
5356
* Material design tab-group component. Supports basic tab pairs (label + content) and includes
@@ -60,15 +63,15 @@ export const _MdTabGroupMixinBase = mixinDisableRipple(MdTabGroupBase);
6063
templateUrl: 'tab-group.html',
6164
styleUrls: ['tab-group.css'],
6265
changeDetection: ChangeDetectionStrategy.OnPush,
63-
inputs: ['disableRipple'],
66+
inputs: ['color', 'disableRipple'],
6467
host: {
6568
'class': 'mat-tab-group',
6669
'[class.mat-tab-group-dynamic-height]': 'dynamicHeight',
6770
'[class.mat-tab-group-inverted-header]': 'headerPosition === "below"',
6871
}
6972
})
7073
export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit,
71-
AfterContentChecked, AfterViewChecked, OnDestroy, CanDisableRipple {
74+
AfterContentChecked, AfterViewChecked, OnDestroy, CanColor, CanDisableRipple {
7275

7376
@ContentChildren(MdTab) _tabs: QueryList<MdTab>;
7477

@@ -109,6 +112,22 @@ export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit
109112
/** Position of the tab header. */
110113
@Input() headerPosition: MdTabHeaderPosition = 'above';
111114

115+
/** Background color of the tab group. */
116+
@Input()
117+
get backgroundColor(): ThemePalette { return this._backgroundColor; }
118+
set backgroundColor(value: ThemePalette) {
119+
let nativeElement = this._elementRef.nativeElement;
120+
121+
this._renderer.removeClass(nativeElement, `mat-background-${this.backgroundColor}`);
122+
123+
if (value) {
124+
this._renderer.addClass(nativeElement, `mat-background-${value}`);
125+
}
126+
127+
this._backgroundColor = value;
128+
}
129+
private _backgroundColor: ThemePalette;
130+
112131
/** Output to enable support for two-way binding on `[(selectedIndex)]` */
113132
@Output() get selectedIndexChange(): Observable<number> {
114133
return map.call(this.selectChange, event => event.index);
@@ -122,8 +141,10 @@ export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit
122141

123142
private _groupId: number;
124143

125-
constructor(private _renderer: Renderer2, private _changeDetectorRef: ChangeDetectorRef) {
126-
super();
144+
constructor(_renderer: Renderer2,
145+
elementRef: ElementRef,
146+
private _changeDetectorRef: ChangeDetectorRef) {
147+
super(_renderer, elementRef);
127148
this._groupId = nextId++;
128149
}
129150

src/lib/tabs/tab-header.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@
6565
.mat-tab-header-pagination-disabled {
6666
box-shadow: none;
6767
cursor: default;
68-
69-
.mat-tab-header-pagination-chevron {
70-
border-color: #ccc;
71-
}
7268
}
7369

7470
.mat-tab-label-container {

src/lib/tabs/tab-nav-bar/tab-nav-bar.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
NgZone,
1818
OnDestroy,
1919
Optional,
20+
Renderer2,
2021
ViewChild,
2122
ViewEncapsulation,
2223
ChangeDetectionStrategy,
@@ -27,27 +28,36 @@ import {CanDisable, mixinDisabled} from '../../core/common-behaviors/disabled';
2728
import {MdRipple} from '../../core';
2829
import {ViewportRuler} from '../../core/overlay/position/viewport-ruler';
2930
import {Directionality, MD_RIPPLE_GLOBAL_OPTIONS, Platform, RippleGlobalOptions} from '../../core';
31+
import {CanColor, mixinColor, ThemePalette} from '../../core/common-behaviors/color';
3032
import {Subject} from 'rxjs/Subject';
3133
import {Subscription} from 'rxjs/Subscription';
3234
import {takeUntil, auditTime} from '../../core/rxjs/index';
3335
import {of as observableOf} from 'rxjs/observable/of';
3436
import {merge} from 'rxjs/observable/merge';
3537
import {fromEvent} from 'rxjs/observable/fromEvent';
3638

39+
// Boilerplate for applying mixins to MdTabNav.
40+
/** @docs-private */
41+
export class MdTabNavBase {
42+
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
43+
}
44+
export const _MdTabNavMixinBase = mixinColor(MdTabNavBase, 'primary');
45+
3746
/**
3847
* Navigation component matching the styles of the tab group header.
3948
* Provides anchored navigation with animated ink bar.
4049
*/
4150
@Component({
4251
moduleId: module.id,
4352
selector: '[md-tab-nav-bar], [mat-tab-nav-bar]',
53+
inputs: ['color'],
4454
templateUrl: 'tab-nav-bar.html',
4555
styleUrls: ['tab-nav-bar.css'],
4656
host: {'class': 'mat-tab-nav-bar'},
4757
encapsulation: ViewEncapsulation.None,
4858
changeDetection: ChangeDetectionStrategy.OnPush,
4959
})
50-
export class MdTabNav implements AfterContentInit, OnDestroy {
60+
export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, CanColor, OnDestroy {
5161
/** Subject that emits when the component has been destroyed. */
5262
private _onDestroy = new Subject<void>();
5363

@@ -59,10 +69,29 @@ export class MdTabNav implements AfterContentInit, OnDestroy {
5969
/** Subscription for window.resize event **/
6070
private _resizeSubscription: Subscription;
6171

62-
constructor(
63-
@Optional() private _dir: Directionality,
64-
private _ngZone: NgZone,
65-
private _changeDetectorRef: ChangeDetectorRef) { }
72+
/** Background color of the tab nav. */
73+
@Input()
74+
get backgroundColor(): ThemePalette { return this._backgroundColor; }
75+
set backgroundColor(value: ThemePalette) {
76+
let nativeElement = this._elementRef.nativeElement;
77+
78+
this._renderer.removeClass(nativeElement, `mat-background-${this.backgroundColor}`);
79+
80+
if (value) {
81+
this._renderer.addClass(nativeElement, `mat-background-${value}`);
82+
}
83+
84+
this._backgroundColor = value;
85+
}
86+
private _backgroundColor: ThemePalette;
87+
88+
constructor(renderer: Renderer2,
89+
elementRef: ElementRef,
90+
@Optional() private _dir: Directionality,
91+
private _ngZone: NgZone,
92+
private _changeDetectorRef: ChangeDetectorRef) {
93+
super(renderer, elementRef);
94+
}
6695

6796
/** Notifies the component that the active link has been changed. */
6897
updateActiveLink(element: ElementRef) {

0 commit comments

Comments
 (0)