Skip to content

Commit ad610ed

Browse files
committed
feat(tabs): add theming and ability to set background color
1 parent 077ebf6 commit ad610ed

File tree

6 files changed

+204
-16
lines changed

6 files changed

+204
-16
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" [background]="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" background="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: 108 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,120 @@
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+
}
2832
}
2933

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+
.mat-tab-group, .mat-tab-nav-bar {
43+
&.mat-primary {
44+
@include _mat-tabs-color($primary);
45+
46+
&.mat-background-primary {
47+
@include _mat-tabs-color($primary, $primary);
48+
}
49+
50+
&.mat-background-accent {
51+
@include _mat-tabs-color($primary, $accent);
52+
}
53+
54+
&.mat-background-warn {
55+
@include _mat-tabs-color($primary, $warn);
56+
}
57+
}
58+
59+
&.mat-accent {
60+
@include _mat-tabs-color($accent);
61+
62+
&.mat-background-primary {
63+
@include _mat-tabs-color($accent, $primary);
64+
}
65+
66+
&.mat-background-accent {
67+
@include _mat-tabs-color($accent, $accent);
68+
}
69+
70+
&.mat-background-warn {
71+
@include _mat-tabs-color($accent, $warn);
72+
}
73+
}
74+
75+
&.mat-warn {
76+
@include _mat-tabs-color($warn);
77+
78+
&.mat-background-primary {
79+
@include _mat-tabs-color($warn, $primary);
80+
}
81+
82+
&.mat-background-accent {
83+
@include _mat-tabs-color($warn, $accent);
84+
}
85+
86+
&.mat-background-warn {
87+
@include _mat-tabs-color($warn, $warn);
88+
}
89+
}
90+
}
91+
}
92+
93+
@mixin _mat-tabs-color($color, $background-color: null) {
94+
95+
$tab-focus-color: if($background-color, $background-color, $color);
96+
97+
// Focus the tab label
98+
.mat-tab-label:focus, .mat-tab-link:focus {
99+
background-color: mat-color($tab-focus-color, lighter, 0.3);
100+
}
101+
102+
// Set the ink bar to the theme color or default-contrast if
103+
// the theme color and background color are the same
30104
.mat-ink-bar {
31-
background-color: mat-color($primary);
105+
background-color: mat-color($color);
106+
107+
@if $background-color == $color {
108+
background-color: mat-color($background-color, default-contrast);
109+
}
32110
}
33111

34-
.mat-tab-label, .mat-tab-link {
35-
color: mat-color($foreground, text);
112+
@if $background-color {
113+
// Set background color for the tab group
114+
.mat-tab-header, .mat-tab-links {
115+
background-color: mat-color($background-color);
116+
}
36117

37-
&.mat-tab-disabled {
38-
color: mat-color($foreground, disabled-text);
118+
// Set labels to contrast against background
119+
.mat-tab-label, .mat-tab-link {
120+
color: mat-color($background-color, default-contrast);
121+
122+
&.mat-tab-disabled {
123+
color: mat-color($background-color, default-contrast, 0.4);
124+
}
125+
}
126+
127+
// Set pagination chevrons to contrast background
128+
.mat-tab-header-pagination-chevron {
129+
border-color: mat-color($background-color, default-contrast);
130+
}
131+
132+
.mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron {
133+
border-color: mat-color($background-color, default-contrast, 0.4);
134+
}
135+
136+
// Remove header border
137+
.mat-tab-header {
138+
border-bottom: none;
139+
border-top: none;
39140
}
40141
}
41142
}

src/lib/tabs/tab-group.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
Renderer2,
1919
} from '@angular/core';
2020
import {coerceBooleanProperty} from '../core';
21+
import {CanColor, mixinColor, ThemePalette} from '../core/common-behaviors/color';
2122
import {Observable} from 'rxjs/Observable';
2223
import {MdTab} from './tab';
2324
import {map} from '../core/rxjs/index';
@@ -35,6 +36,12 @@ export class MdTabChangeEvent {
3536
/** Possible positions for the tab header. */
3637
export type MdTabHeaderPosition = 'above' | 'below';
3738

39+
// Boilerplate for applying mixins to MdTabGroup.
40+
export class MdTabGroupBase {
41+
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
42+
}
43+
export const _MdTabGroupMixinBase = mixinColor(MdTabGroupBase, 'primary');
44+
3845
/**
3946
* Material design tab-group component. Supports basic tab pairs (label + content) and includes
4047
* animated ink-bar, keyboard navigation, and screen reader.
@@ -43,6 +50,7 @@ export type MdTabHeaderPosition = 'above' | 'below';
4350
@Component({
4451
moduleId: module.id,
4552
selector: 'md-tab-group, mat-tab-group',
53+
inputs: ['color'],
4654
templateUrl: 'tab-group.html',
4755
styleUrls: ['tab-group.css'],
4856
host: {
@@ -51,7 +59,7 @@ export type MdTabHeaderPosition = 'above' | 'below';
5159
'[class.mat-tab-group-inverted-header]': 'headerPosition === "below"',
5260
}
5361
})
54-
export class MdTabGroup {
62+
export class MdTabGroup extends _MdTabGroupMixinBase implements CanColor {
5563
@ContentChildren(MdTab) _tabs: QueryList<MdTab>;
5664

5765
@ViewChild('tabBodyWrapper') _tabBodyWrapper: ElementRef;
@@ -94,6 +102,22 @@ export class MdTabGroup {
94102
@Input()
95103
headerPosition: MdTabHeaderPosition = 'above';
96104

105+
/** Background color of the tab group. */
106+
@Input()
107+
get background(): ThemePalette { return this._background; }
108+
set background(value: ThemePalette) {
109+
let nativeElement = this._elementRef.nativeElement;
110+
111+
this._renderer.removeClass(nativeElement, `mat-background-${this.background}`);
112+
113+
if (value) {
114+
this._renderer.addClass(nativeElement, `mat-background-${value}`);
115+
}
116+
117+
this._background = value;
118+
}
119+
private _background: ThemePalette;
120+
97121
/** Output to enable support for two-way binding on `[(selectedIndex)]` */
98122
@Output() get selectedIndexChange(): Observable<number> {
99123
return map.call(this.selectChange, event => event.index);
@@ -107,7 +131,9 @@ export class MdTabGroup {
107131

108132
private _groupId: number;
109133

110-
constructor(private _renderer: Renderer2) {
134+
constructor(_renderer: Renderer2,
135+
elementRef: ElementRef) {
136+
super(_renderer, elementRef);
111137
this._groupId = nextId++;
112138
}
113139

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: 32 additions & 2 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
} from '@angular/core';
@@ -25,26 +26,34 @@ import {CanDisable, mixinDisabled} from '../../core/common-behaviors/disabled';
2526
import {MdRipple} from '../../core';
2627
import {ViewportRuler} from '../../core/overlay/position/viewport-ruler';
2728
import {Directionality, MD_RIPPLE_GLOBAL_OPTIONS, Platform, RippleGlobalOptions} from '../../core';
29+
import {CanColor, mixinColor, ThemePalette} from '../../core/common-behaviors/color';
2830
import {Subject} from 'rxjs/Subject';
2931
import {Subscription} from 'rxjs/Subscription';
3032
import {takeUntil, auditTime} from '../../core/rxjs/index';
3133
import {of as observableOf} from 'rxjs/observable/of';
3234
import {merge} from 'rxjs/observable/merge';
3335
import {fromEvent} from 'rxjs/observable/fromEvent';
3436

37+
// Boilerplate for applying mixins to MdTabNav.
38+
export class MdTabNavBase {
39+
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
40+
}
41+
export const _MdTabNavMixinBase = mixinColor(MdTabNavBase, 'primary');
42+
3543
/**
3644
* Navigation component matching the styles of the tab group header.
3745
* Provides anchored navigation with animated ink bar.
3846
*/
3947
@Component({
4048
moduleId: module.id,
4149
selector: '[md-tab-nav-bar], [mat-tab-nav-bar]',
50+
inputs: ['color'],
4251
templateUrl: 'tab-nav-bar.html',
4352
styleUrls: ['tab-nav-bar.css'],
4453
host: {'class': 'mat-tab-nav-bar'},
4554
encapsulation: ViewEncapsulation.None,
4655
})
47-
export class MdTabNav implements AfterContentInit, OnDestroy {
56+
export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, CanColor, OnDestroy {
4857
/** Subject that emits when the component has been destroyed. */
4958
private _onDestroy = new Subject<void>();
5059

@@ -56,7 +65,28 @@ export class MdTabNav implements AfterContentInit, OnDestroy {
5665
/** Subscription for window.resize event **/
5766
private _resizeSubscription: Subscription;
5867

59-
constructor(@Optional() private _dir: Directionality, private _ngZone: NgZone) { }
68+
/** Background color of the tab nav. */
69+
@Input()
70+
get background(): ThemePalette { return this._background; }
71+
set background(value: ThemePalette) {
72+
let nativeElement = this._elementRef.nativeElement;
73+
74+
this._renderer.removeClass(nativeElement, `mat-background-${this.background}`);
75+
76+
if (value) {
77+
this._renderer.addClass(nativeElement, `mat-background-${value}`);
78+
}
79+
80+
this._background = value;
81+
}
82+
private _background: ThemePalette;
83+
84+
constructor(renderer: Renderer2,
85+
elementRef: ElementRef,
86+
private _ngZone: NgZone,
87+
@Optional() private _dir: Directionality) {
88+
super(renderer, elementRef);
89+
}
6090

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

0 commit comments

Comments
 (0)