Skip to content

Commit

Permalink
feat(tab-nav-bar): allow disabling ripples for links (#6273)
Browse files Browse the repository at this point in the history
* Adds a possibility to disable ripples for a tab-nav-bar with links.

Closes #6245
  • Loading branch information
devversion authored and mmalerba committed Aug 8, 2017
1 parent c20bcf9 commit 4ae1b0f
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/lib/core/ripple/ripple.ts
Expand Up @@ -135,7 +135,7 @@ export class MdRipple implements OnChanges, OnDestroy {
}

/** Updates the ripple renderer with the latest ripple configuration. */
private _updateRippleRenderer() {
_updateRippleRenderer() {
this._rippleRenderer.rippleDisabled = this._globalOptions.disabled || this.disabled;
this._rippleRenderer.rippleConfig = this.rippleConfig;
}
Expand Down
33 changes: 31 additions & 2 deletions src/lib/tabs/tab-nav-bar/tab-nav-bar.spec.ts
@@ -1,6 +1,6 @@
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import {MdTabsModule} from '../index';
import {MdTabNav} from './tab-nav-bar';
import {MdTabNav, MdTabLink} from './tab-nav-bar';
import {Component, ViewChild} from '@angular/core';
import {By} from '@angular/platform-browser';
import {ViewportRuler} from '../../core/overlay/position/viewport-ruler';
Expand Down Expand Up @@ -81,6 +81,20 @@ describe('MdTabNavBar', () => {
.toBe(true, 'Expected aria-disabled to be set to "true" if link is disabled.');
});

it('should update the disableRipple property on each tab link', () => {
const tabLinkElements = fixture.debugElement.queryAll(By.directive(MdTabLink))
.map(tabLinkDebug => tabLinkDebug.componentInstance) as MdTabLink[];

expect(tabLinkElements.every(tabLink => !tabLink.disableRipple))
.toBe(true, 'Expected every tab link to have ripples enabled');

fixture.componentInstance.disableRipple = true;
fixture.detectChanges();

expect(tabLinkElements.every(tabLink => tabLink.disableRipple))
.toBe(true, 'Expected every tab link to have ripples disabled');
});

it('should update the tabindex if links are disabled', () => {
const tabLinkElements = fixture.debugElement.queryAll(By.css('a'))
.map(tabLinkDebugEl => tabLinkDebugEl.nativeElement);
Expand All @@ -105,6 +119,20 @@ describe('MdTabNavBar', () => {
.toBe(1, 'Expected one ripple to show up if user clicks on tab link.');
});

it('should be able to disable ripples on a tab link', () => {
const tabLinkDebug = fixture.debugElement.query(By.css('a'));
const tabLinkElement = tabLinkDebug.nativeElement;
const tabLinkInstance = tabLinkDebug.injector.get(MdTabLink);

tabLinkInstance.disableRipple = true;

dispatchMouseEvent(tabLinkElement, 'mousedown');
dispatchMouseEvent(tabLinkElement, 'mouseup');

expect(tabLinkElement.querySelectorAll('.mat-ripple-element').length)
.toBe(0, 'Expected no ripple to show up if ripples are disabled.');
});

it('should re-align the ink bar when the direction changes', () => {
const inkBar = fixture.componentInstance.tabNavBar._inkBar;

Expand Down Expand Up @@ -173,7 +201,7 @@ describe('MdTabNavBar', () => {
@Component({
selector: 'test-app',
template: `
<nav md-tab-nav-bar>
<nav md-tab-nav-bar [disableRipple]="disableRipple">
<a md-tab-link
*ngFor="let tab of tabs; let index = index"
[active]="activeIndex === index"
Expand All @@ -189,6 +217,7 @@ class SimpleTabNavBarTestApp {

label = '';
disabled: boolean = false;
disableRipple: boolean = false;
tabs = [0, 1, 2];

activeIndex = 0;
Expand Down
44 changes: 41 additions & 3 deletions src/lib/tabs/tab-nav-bar/tab-nav-bar.ts
Expand Up @@ -21,6 +21,9 @@ import {
ViewEncapsulation,
ChangeDetectionStrategy,
ChangeDetectorRef,
ContentChildren,
QueryList,
forwardRef,
} from '@angular/core';
import {MdInkBar} from '../ink-bar';
import {CanDisable, mixinDisabled} from '../../core/common-behaviors/disabled';
Expand All @@ -34,13 +37,15 @@ import {takeUntil, auditTime} from '../../core/rxjs/index';
import {of as observableOf} from 'rxjs/observable/of';
import {merge} from 'rxjs/observable/merge';
import {fromEvent} from 'rxjs/observable/fromEvent';
import {CanDisableRipple, mixinDisableRipple} from '../../core/common-behaviors/disable-ripple';
import {coerceBooleanProperty} from '@angular/cdk/coercion';

// Boilerplate for applying mixins to MdTabNav.
/** @docs-private */
export class MdTabNavBase {
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
}
export const _MdTabNavMixinBase = mixinColor(MdTabNavBase, 'primary');
export const _MdTabNavMixinBase = mixinDisableRipple(mixinColor(MdTabNavBase, 'primary'));

/**
* Navigation component matching the styles of the tab group header.
Expand All @@ -49,14 +54,16 @@ export const _MdTabNavMixinBase = mixinColor(MdTabNavBase, 'primary');
@Component({
moduleId: module.id,
selector: '[md-tab-nav-bar], [mat-tab-nav-bar]',
inputs: ['color'],
inputs: ['color', 'disableRipple'],
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 extends _MdTabNavMixinBase implements AfterContentInit, CanColor, OnDestroy {
export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, CanColor,
CanDisableRipple, OnDestroy {

/** Subject that emits when the component has been destroyed. */
private _onDestroy = new Subject<void>();

Expand All @@ -65,6 +72,10 @@ export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, Ca

@ViewChild(MdInkBar) _inkBar: MdInkBar;

/** Query list of all tab links of the tab navigation. */
@ContentChildren(forwardRef(() => MdTabLink), {descendants: true})
_tabLinks: QueryList<MdTabLink>;

/** Subscription for window.resize event **/
private _resizeSubscription: Subscription;

Expand All @@ -84,6 +95,14 @@ export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, Ca
}
private _backgroundColor: ThemePalette;

/** Whether ripples should be disabled for all links or not. */
get disableRipple() { return this._disableRipple; }
set disableRipple(value: boolean) {
this._disableRipple = coerceBooleanProperty(value);
this._setLinkDisableRipple();
}
private _disableRipple: boolean = false;

constructor(renderer: Renderer2,
elementRef: ElementRef,
@Optional() private _dir: Directionality,
Expand Down Expand Up @@ -112,6 +131,7 @@ export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, Ca
return takeUntil.call(merge(dirChange, resize), this._onDestroy)
.subscribe(() => this._alignInkBar());
});
this._setLinkDisableRipple();
}

/** Checks if the active link has been changed and, if so, will update the ink bar. */
Expand All @@ -136,6 +156,13 @@ export class MdTabNav extends _MdTabNavMixinBase implements AfterContentInit, Ca
this._inkBar.alignToElement(this._activeLinkElement.nativeElement);
}
}

/** Sets the `disableRipple` property on each link of the navigation bar. */
private _setLinkDisableRipple() {
if (this._tabLinks) {
this._tabLinks.forEach(link => link.disableRipple = this.disableRipple);
}
}
}


Expand All @@ -160,6 +187,9 @@ export class MdTabLink extends _MdTabLinkMixinBase implements OnDestroy, CanDisa
/** Whether the tab link is active or not. */
private _isActive: boolean = false;

/** Whether the ripples for this tab should be disabled or not. */
private _disableRipple: boolean = false;

/** Reference to the instance of the ripple for the tab link. */
private _tabLinkRipple: MdRipple;

Expand All @@ -173,6 +203,14 @@ export class MdTabLink extends _MdTabLinkMixinBase implements OnDestroy, CanDisa
}
}

/** Whether ripples should be disabled or not. */
get disableRipple(): boolean { return this._disableRipple; }
set disableRipple(value: boolean) {
this._disableRipple = value;
this._tabLinkRipple.disabled = this.disableRipple;
this._tabLinkRipple._updateRippleRenderer();
}

/** @docs-private */
get tabIndex(): number {
return this.disabled ? -1 : 0;
Expand Down

0 comments on commit 4ae1b0f

Please sign in to comment.