Skip to content

Commit

Permalink
feat(list): add ripples to list items that are links (#930)
Browse files Browse the repository at this point in the history
* feat(list): add ripples to list items that are links

* Add MdRippleModule to imports
  • Loading branch information
dozingcat authored and mmalerba committed Mar 15, 2017
1 parent 05c865d commit aa3360a
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 8 deletions.
11 changes: 7 additions & 4 deletions src/lib/list/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {NgModule, ModuleWithProviders} from '@angular/core';
import {MdLineModule, CompatibilityModule} from '../core';
import {MdLineModule, MdRippleModule, CompatibilityModule} from '../core';
import {
MdList,
MdListItem,
Expand All @@ -10,11 +10,12 @@ import {
MdNavListCssMatStyler,
MdDividerCssMatStyler,
MdListSubheaderCssMatStyler,
MdNavListTokenSetter,
} from './list';


@NgModule({
imports: [MdLineModule, CompatibilityModule],
imports: [MdLineModule, MdRippleModule, CompatibilityModule],
exports: [
MdList,
MdListItem,
Expand All @@ -26,7 +27,8 @@ import {
MdListCssMatStyler,
MdNavListCssMatStyler,
MdDividerCssMatStyler,
MdListSubheaderCssMatStyler
MdListSubheaderCssMatStyler,
MdNavListTokenSetter,
],
declarations: [
MdList,
Expand All @@ -37,7 +39,8 @@ import {
MdListCssMatStyler,
MdNavListCssMatStyler,
MdDividerCssMatStyler,
MdListSubheaderCssMatStyler
MdListSubheaderCssMatStyler,
MdNavListTokenSetter,
],
})
export class MdListModule {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/list/list-item.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<div class="mat-list-item-content" [class.mat-list-item-focus]="_hasFocus">
<div class="mat-list-item-content" [class.mat-list-item-focus]="_hasFocus"
md-ripple [mdRippleDisabled]="!isRippleEnabled()">
<ng-content
select="[md-list-avatar],[md-list-icon], [mat-list-avatar], [mat-list-icon]"></ng-content>
<div class="mat-list-text"><ng-content select="[md-line], [mat-line]"></ng-content></div>
Expand Down
1 change: 1 addition & 0 deletions src/lib/list/list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ $mat-dense-three-line-height: 76px;
font-size: $font-size;
height: $base-height;
padding: 0 $mat-list-side-padding;
position: relative;
}

&.mat-list-item-avatar .mat-list-item-content {
Expand Down
43 changes: 41 additions & 2 deletions src/lib/list/list.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {async, TestBed} from '@angular/core/testing';
import {Component} from '@angular/core';
import {Component, QueryList, ViewChildren} from '@angular/core';
import {By} from '@angular/platform-browser';
import {MdListItem, MdListModule} from './index';

Expand All @@ -19,6 +19,7 @@ describe('MdList', () => {
ListWithDynamicNumberOfLines,
ListWithMultipleItems,
ListWithManyLines,
NavListWithOneAnchorItem,
],
});

Expand Down Expand Up @@ -114,6 +115,29 @@ describe('MdList', () => {
expect(list.nativeElement.getAttribute('role')).toBe('list');
expect(listItem.nativeElement.getAttribute('role')).toBe('listitem');
});

it('should not show ripples for non-nav lists', () => {
let fixture = TestBed.createComponent(ListWithOneAnchorItem);
fixture.detectChanges();

const items: QueryList<MdListItem> = fixture.debugElement.componentInstance.listItems;
expect(items.length).toBeGreaterThan(0);
items.forEach(item => expect(item.isRippleEnabled()).toBe(false));
});

it('should maybe show ripples for nav lists', () => {
let fixture = TestBed.createComponent(NavListWithOneAnchorItem);
fixture.detectChanges();

const items: QueryList<MdListItem> = fixture.debugElement.componentInstance.listItems;
expect(items.length).toBeGreaterThan(0);
// Ripples should be enabled by default, and can be disabled with a binding.
items.forEach(item => expect(item.isRippleEnabled()).toBe(true));

fixture.debugElement.componentInstance.disableRipple = true;
fixture.detectChanges();
items.forEach(item => expect(item.isRippleEnabled()).toBe(false));
});
});


Expand All @@ -132,7 +156,22 @@ class BaseTestList {
Paprika
</a>
</md-list>`})
class ListWithOneAnchorItem extends BaseTestList { }
class ListWithOneAnchorItem extends BaseTestList {
// This needs to be declared directly on the class; if declared on the BaseTestList superclass,
// it doesn't get populated.
@ViewChildren(MdListItem) listItems: QueryList<MdListItem>;
}

@Component({template: `
<md-nav-list>
<a md-list-item [disableRipple]="disableRipple">
Paprika
</a>
</md-nav-list>`})
class NavListWithOneAnchorItem extends BaseTestList {
@ViewChildren(MdListItem) listItems: QueryList<MdListItem>;
disableRipple: boolean = false;
}

@Component({template: `
<md-list>
Expand Down
36 changes: 35 additions & 1 deletion src/lib/list/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import {
QueryList,
Directive,
ElementRef,
Inject,
Input,
OpaqueToken,
Optional,
Renderer,
AfterContentInit,
} from '@angular/core';
Expand All @@ -16,13 +20,23 @@ import {MdLine, MdLineSetter} from '../core';
})
export class MdListDivider {}

/**
* Token used to inject the list type into child MdListItem components so they can know whether
* they're in a nav list (and thus should use an MdRipple).
*/
export const LIST_TYPE_TOKEN = new OpaqueToken('list_type');

const NORMAL_LIST_TYPE = 'normal_list_type';
const NAV_LIST_TYPE = 'nav_list_type';

@Component({
moduleId: module.id,
selector: 'md-list, mat-list, md-nav-list, mat-nav-list',
host: {
'role': 'list'},
template: '<ng-content></ng-content>',
styleUrls: ['list.css'],
providers: [{ provide: LIST_TYPE_TOKEN, useValue: NORMAL_LIST_TYPE }],
encapsulation: ViewEncapsulation.None
})
export class MdList {}
Expand Down Expand Up @@ -51,6 +65,15 @@ export class MdListCssMatStyler {}
})
export class MdNavListCssMatStyler {}

/**
* Directive to set the ListType token to NAV_LIST_TYPE.
*/
@Directive({
selector: 'md-nav-list, mat-nav-list',
providers: [{ provide: LIST_TYPE_TOKEN, useValue: NAV_LIST_TYPE }],
})
export class MdNavListTokenSetter {}

/**
* Directive whose purpose is to add the mat- CSS styling to this selector.
* @docs-private
Expand Down Expand Up @@ -112,6 +135,11 @@ export class MdListSubheaderCssMatStyler {}
encapsulation: ViewEncapsulation.None
})
export class MdListItem implements AfterContentInit {
/**
* Whether the ripple effect on click should be disabled. This applies only to list items that
* are children of an md-nav-list; md-list items never have ripples.
*/
@Input() disableRipple: boolean = false;
_hasFocus: boolean = false;

private _lineSetter: MdLineSetter;
Expand All @@ -124,12 +152,18 @@ export class MdListItem implements AfterContentInit {
this._element.nativeElement, 'mat-list-item-avatar', avatar != null);
}

constructor(private _renderer: Renderer, private _element: ElementRef) {}
constructor(private _renderer: Renderer, private _element: ElementRef,
@Optional() @Inject(LIST_TYPE_TOKEN) private _listType: string) {}

ngAfterContentInit() {
this._lineSetter = new MdLineSetter(this._lines, this._renderer, this._element);
}

/** Whether this list item should show a ripple effect when clicked. */
isRippleEnabled() {
return !this.disableRipple && (this._listType === NAV_LIST_TYPE);
}

_handleFocus() {
this._hasFocus = true;
}
Expand Down

0 comments on commit aa3360a

Please sign in to comment.