diff --git a/src/demo-app/tabs/tabs-demo.html b/src/demo-app/tabs/tabs-demo.html index e96d3b67e9cc..421f8240ee9c 100644 --- a/src/demo-app/tabs/tabs-demo.html +++ b/src/demo-app/tabs/tabs-demo.html @@ -3,9 +3,10 @@

Tab Nav Bar

+
-
+ +

Accent tabs

+ + +
+ This tab is about the Earth! +
+
+ +
+ This tab is about combustion! +
+
+
+ +

Tabs with background color

+ + +
+ This tab is about the Earth! +
+
+ +
+ This tab is about combustion! +
+
+
diff --git a/src/demo-app/tabs/tabs-demo.ts b/src/demo-app/tabs/tabs-demo.ts index 447fb2794eca..d5eedce2ef86 100644 --- a/src/demo-app/tabs/tabs-demo.ts +++ b/src/demo-app/tabs/tabs-demo.ts @@ -16,6 +16,8 @@ export class TabsDemo { {label: 'Fog', link: 'foggy-tab'}, ]; + tabNavBackground: any = undefined; + // Standard tabs demo tabs = [ { @@ -93,6 +95,10 @@ export class TabsDemo { addToLabel() { this.tabLinks.forEach(link => link.label += 'extracontent'); } + + toggleBackground() { + this.tabNavBackground = this.tabNavBackground ? undefined : 'primary'; + } } diff --git a/src/lib/tabs/_tabs-theme.scss b/src/lib/tabs/_tabs-theme.scss index 0f6238e97549..a0874b1c3c7d 100644 --- a/src/lib/tabs/_tabs-theme.scss +++ b/src/lib/tabs/_tabs-theme.scss @@ -23,21 +23,94 @@ } } - .mat-tab-label:focus { - background-color: mat-color($primary, lighter, 0.3); + .mat-tab-label, .mat-tab-link { + color: mat-color($foreground, text); + + &.mat-tab-disabled { + color: mat-color($foreground, disabled-text); + } + } + + .mat-tab-header-pagination-chevron { + border-color: mat-color($foreground, text); + } + + .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron { + border-color: mat-color($foreground, disabled-text); + } + + // Remove header border when there is a background color + .mat-tab-group[class*='mat-background-'] .mat-tab-header, + .mat-tab-nav-bar[class*='mat-background-'] { + border-bottom: none; + border-top: none; + } + + .mat-tab-group, .mat-tab-nav-bar { + $theme-colors: ( + primary: $primary, + accent: $accent, + warn: $warn + ); + + @each $name, $color in $theme-colors { + // Set the foreground color of the tabs + &.mat-#{$name} { + @include _mat-tab-label-focus($color); + @include _mat-ink-bar($color); + + // Override ink bar when background color is the same + &.mat-background-#{$name} { + @include _mat-ink-bar($color, default-contrast); + } + } + } + + @each $name, $color in $theme-colors { + // Set background color of the tabs and override focus color + &.mat-background-#{$name} { + @include _mat-tab-label-focus($color); + @include _mat-tabs-background($color); + } + } } +} +@mixin _mat-ink-bar($color, $hue: default) { .mat-ink-bar { - background-color: mat-color($primary); + background-color: mat-color($color, $hue); + } +} + +@mixin _mat-tab-label-focus($tab-focus-color) { + .mat-tab-label:focus, .mat-tab-link:focus { + background-color: mat-color($tab-focus-color, lighter, 0.3); + } +} + +@mixin _mat-tabs-background($background-color) { + // Set background color for the tab group + .mat-tab-header, .mat-tab-links { + background-color: mat-color($background-color); } + // Set labels to contrast against background .mat-tab-label, .mat-tab-link { - color: mat-color($foreground, text); + color: mat-color($background-color, default-contrast); &.mat-tab-disabled { - color: mat-color($foreground, disabled-text); + color: mat-color($background-color, default-contrast, 0.4); } } + + // Set pagination chevrons to contrast background + .mat-tab-header-pagination-chevron { + border-color: mat-color($background-color, default-contrast); + } + + .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron { + border-color: mat-color($background-color, default-contrast, 0.4); + } } @mixin mat-tabs-typography($config) { diff --git a/src/lib/tabs/tab-group.ts b/src/lib/tabs/tab-group.ts index edfbb81ddea1..4230db2954e8 100644 --- a/src/lib/tabs/tab-group.ts +++ b/src/lib/tabs/tab-group.ts @@ -30,6 +30,7 @@ import {MdTab} from './tab'; import {map} from '../core/rxjs/index'; import {merge} from 'rxjs/observable/merge'; import {CanDisableRipple, mixinDisableRipple} from '../core/common-behaviors/disable-ripple'; +import {CanColor, mixinColor, ThemePalette} from '../core/common-behaviors/color'; /** Used to generate unique ID's for each tab component */ @@ -46,8 +47,10 @@ export type MdTabHeaderPosition = 'above' | 'below'; // Boilerplate for applying mixins to MdTabGroup. /** @docs-private */ -export class MdTabGroupBase {} -export const _MdTabGroupMixinBase = mixinDisableRipple(MdTabGroupBase); +export class MdTabGroupBase { + constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {} +} +export const _MdTabGroupMixinBase = mixinColor(mixinDisableRipple(MdTabGroupBase), 'primary'); /** * Material design tab-group component. Supports basic tab pairs (label + content) and includes @@ -60,7 +63,7 @@ export const _MdTabGroupMixinBase = mixinDisableRipple(MdTabGroupBase); templateUrl: 'tab-group.html', styleUrls: ['tab-group.css'], changeDetection: ChangeDetectionStrategy.OnPush, - inputs: ['disableRipple'], + inputs: ['color', 'disableRipple'], host: { 'class': 'mat-tab-group', '[class.mat-tab-group-dynamic-height]': 'dynamicHeight', @@ -68,7 +71,7 @@ export const _MdTabGroupMixinBase = mixinDisableRipple(MdTabGroupBase); } }) export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit, - AfterContentChecked, AfterViewChecked, OnDestroy, CanDisableRipple { + AfterContentChecked, AfterViewChecked, OnDestroy, CanColor, CanDisableRipple { @ContentChildren(MdTab) _tabs: QueryList; @@ -109,6 +112,22 @@ export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit /** Position of the tab header. */ @Input() headerPosition: MdTabHeaderPosition = 'above'; + /** Background color of the tab group. */ + @Input() + get backgroundColor(): ThemePalette { return this._backgroundColor; } + set backgroundColor(value: ThemePalette) { + let nativeElement = this._elementRef.nativeElement; + + this._renderer.removeClass(nativeElement, `mat-background-${this.backgroundColor}`); + + if (value) { + this._renderer.addClass(nativeElement, `mat-background-${value}`); + } + + this._backgroundColor = value; + } + private _backgroundColor: ThemePalette; + /** Output to enable support for two-way binding on `[(selectedIndex)]` */ @Output() get selectedIndexChange(): Observable { return map.call(this.selectChange, event => event.index); @@ -122,8 +141,10 @@ export class MdTabGroup extends _MdTabGroupMixinBase implements AfterContentInit private _groupId: number; - constructor(private _renderer: Renderer2, private _changeDetectorRef: ChangeDetectorRef) { - super(); + constructor(_renderer: Renderer2, + elementRef: ElementRef, + private _changeDetectorRef: ChangeDetectorRef) { + super(_renderer, elementRef); this._groupId = nextId++; } diff --git a/src/lib/tabs/tab-header.scss b/src/lib/tabs/tab-header.scss index 3e5f4bf75341..7cb991a472c5 100644 --- a/src/lib/tabs/tab-header.scss +++ b/src/lib/tabs/tab-header.scss @@ -65,10 +65,6 @@ .mat-tab-header-pagination-disabled { box-shadow: none; cursor: default; - - .mat-tab-header-pagination-chevron { - border-color: #ccc; - } } .mat-tab-label-container { diff --git a/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts b/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts index bdd2600ea515..3644ed567c01 100644 --- a/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts +++ b/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts @@ -17,6 +17,7 @@ import { NgZone, OnDestroy, Optional, + Renderer2, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, @@ -27,6 +28,7 @@ import {CanDisable, mixinDisabled} from '../../core/common-behaviors/disabled'; import {MdRipple} from '../../core'; import {ViewportRuler} from '../../core/overlay/position/viewport-ruler'; import {Directionality, MD_RIPPLE_GLOBAL_OPTIONS, Platform, RippleGlobalOptions} from '../../core'; +import {CanColor, mixinColor, ThemePalette} from '../../core/common-behaviors/color'; import {Subject} from 'rxjs/Subject'; import {Subscription} from 'rxjs/Subscription'; import {takeUntil, auditTime} from '../../core/rxjs/index'; @@ -34,6 +36,13 @@ import {of as observableOf} from 'rxjs/observable/of'; import {merge} from 'rxjs/observable/merge'; import {fromEvent} from 'rxjs/observable/fromEvent'; +// Boilerplate for applying mixins to MdTabNav. +/** @docs-private */ +export class MdTabNavBase { + constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {} +} +export const _MdTabNavMixinBase = mixinColor(MdTabNavBase, 'primary'); + /** * Navigation component matching the styles of the tab group header. * Provides anchored navigation with animated ink bar. @@ -41,13 +50,14 @@ import {fromEvent} from 'rxjs/observable/fromEvent'; @Component({ moduleId: module.id, selector: '[md-tab-nav-bar], [mat-tab-nav-bar]', + inputs: ['color'], templateUrl: 'tab-nav-bar.html', styleUrls: ['tab-nav-bar.css'], host: {'class': 'mat-tab-nav-bar'}, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MdTabNav implements AfterContentInit, OnDestroy { +export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, CanColor, OnDestroy { /** Subject that emits when the component has been destroyed. */ private _onDestroy = new Subject(); @@ -59,10 +69,29 @@ export class MdTabNav implements AfterContentInit, OnDestroy { /** Subscription for window.resize event **/ private _resizeSubscription: Subscription; - constructor( - @Optional() private _dir: Directionality, - private _ngZone: NgZone, - private _changeDetectorRef: ChangeDetectorRef) { } + /** Background color of the tab nav. */ + @Input() + get backgroundColor(): ThemePalette { return this._backgroundColor; } + set backgroundColor(value: ThemePalette) { + let nativeElement = this._elementRef.nativeElement; + + this._renderer.removeClass(nativeElement, `mat-background-${this.backgroundColor}`); + + if (value) { + this._renderer.addClass(nativeElement, `mat-background-${value}`); + } + + this._backgroundColor = value; + } + private _backgroundColor: ThemePalette; + + constructor(renderer: Renderer2, + elementRef: ElementRef, + @Optional() private _dir: Directionality, + private _ngZone: NgZone, + private _changeDetectorRef: ChangeDetectorRef) { + super(renderer, elementRef); + } /** Notifies the component that the active link has been changed. */ updateActiveLink(element: ElementRef) {