diff --git a/src/components/grid-list/grid-list.scss b/src/components/grid-list/grid-list.scss
index d2372096a135..f0024520cad3 100644
--- a/src/components/grid-list/grid-list.scss
+++ b/src/components/grid-list/grid-list.scss
@@ -1,4 +1,15 @@
-// TODO(kara): Review this to see if MD spec updates are needed
+@import "list-shared";
+
+/* height of tile header or footer if it has one line */
+$md-grid-list-one-line-height: 48px;
+/* height of tile header or footer if it has two lines */
+$md-grid-list-two-line-height: 68px;
+/* side padding for text in tile headers and footers */
+$md-grid-list-text-padding: 16px;
+
+/* font styles for text in tile headers and footers */
+$md-grid-list-font-size: 16px;
+$md-grid-list-secondary-font: 12px;
md-grid-list {
display: block;
@@ -29,32 +40,30 @@ md-grid-tile {
// Headers & footers
md-grid-tile-header,
md-grid-tile-footer {
+ @include md-line-base($md-grid-list-secondary-font);
+ @include md-normalize-text();
+
display: flex;
- flex-direction: row;
align-items: center;
- height: 48px;
+ height: $md-grid-list-one-line-height;
color: #fff;
background: rgba(0, 0, 0, 0.18);
overflow: hidden;
+ padding: 0 $md-grid-list-text-padding;
+ font-size: $md-grid-list-font-size;
// Positioning
position: absolute;
left: 0;
right: 0;
- h3,
- h4 {
- font-weight: 400;
- margin: 0 0 0 16px;
- }
-
- h3 {
- font-size: 14px;
+ &.md-2-line {
+ height: $md-grid-list-two-line-height;
}
+ }
- h4 {
- font-size: 12px;
- }
+ .md-grid-list-text {
+ @include md-line-wrapper-base();
}
md-grid-tile-header {
@@ -64,4 +73,17 @@ md-grid-tile {
md-grid-tile-footer {
bottom: 0;
}
+
+ [md-grid-avatar] {
+ padding-right: $md-grid-list-text-padding;
+
+ [dir='rtl'] & {
+ padding-right: 0;
+ padding-left: $md-grid-list-text-padding;
+ }
+
+ &:empty {
+ display:none;
+ }
+ }
}
diff --git a/src/components/grid-list/grid-list.spec.ts b/src/components/grid-list/grid-list.spec.ts
index 55fe5936478c..481369193388 100644
--- a/src/components/grid-list/grid-list.spec.ts
+++ b/src/components/grid-list/grid-list.spec.ts
@@ -12,7 +12,7 @@ import {Component} from '@angular/core';
import {By} from '@angular/platform-browser';
import {MD_GRID_LIST_DIRECTIVES, MdGridList} from './grid-list';
-import {MdGridTile} from './grid-tile';
+import {MdGridTile, MdGridTileText} from './grid-tile';
describe('MdGridList', () => {
let builder: TestComponentBuilder;
@@ -374,6 +374,48 @@ describe('MdGridList', () => {
});
});
});
+
+ it('should add not add any classes to footers without lines', () => {
+ var template = `
+
+
+
+ I'm a footer!
+
+
+
+ `;
+
+ return builder.overrideTemplate(TestGridList, template)
+ .createAsync(TestGridList).then((fixture: ComponentFixture) => {
+ fixture.detectChanges();
+
+ let footer = fixture.debugElement.query(By.directive(MdGridTileText));
+ expect(footer.nativeElement.classList.contains('md-2-line')).toBe(false);
+ });
+ });
+
+ it('should add class to footers with two lines', () => {
+ var template = `
+
+
+
+ First line
+ Second line
+
+
+
+ `;
+
+ return builder.overrideTemplate(TestGridList, template)
+ .createAsync(TestGridList).then((fixture: ComponentFixture) => {
+ fixture.detectChanges();
+
+ let footer = fixture.debugElement.query(By.directive(MdGridTileText));
+ expect(footer.nativeElement.classList.contains('md-2-line')).toBe(true);
+ });
+ });
+
});
@Component({
diff --git a/src/components/grid-list/grid-list.ts b/src/components/grid-list/grid-list.ts
index cecf34e6a050..e1b7c65804a8 100644
--- a/src/components/grid-list/grid-list.ts
+++ b/src/components/grid-list/grid-list.ts
@@ -10,7 +10,7 @@ import {
ElementRef,
Optional
} from '@angular/core';
-import {MdGridTile} from './grid-tile';
+import {MdGridTile, MdGridTileText} from './grid-tile';
import {TileCoordinator} from './tile-coordinator';
import {
TileStyler,
@@ -20,6 +20,7 @@ import {
} from './tile-styler';
import {MdGridListColsError} from './grid-list-errors';
import {Dir} from '@angular2-material/core/rtl/dir';
+import {MdLine} from '@angular2-material/core/line/line';
// TODO(kara): Conditional (responsive) column count / row size.
// TODO(kara): Re-layout on window resize / media change (debounced).
@@ -167,4 +168,4 @@ export function coerceToNumber(value: string | number): number {
return typeof value === 'string' ? parseInt(value, 10) : value;
}
-export const MD_GRID_LIST_DIRECTIVES: any[] = [MdGridList, MdGridTile];
+export const MD_GRID_LIST_DIRECTIVES: any[] = [MdGridList, MdGridTile, MdLine, MdGridTileText];
diff --git a/src/components/grid-list/grid-tile-text.html b/src/components/grid-list/grid-tile-text.html
new file mode 100644
index 000000000000..9946619e7f13
--- /dev/null
+++ b/src/components/grid-list/grid-tile-text.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/src/components/grid-list/grid-tile.ts b/src/components/grid-list/grid-tile.ts
index 3e3088f8d2c9..a709d85f8b40 100644
--- a/src/components/grid-list/grid-tile.ts
+++ b/src/components/grid-list/grid-tile.ts
@@ -4,9 +4,12 @@ import {
Renderer,
ElementRef,
Input,
+ ContentChildren,
+ QueryList,
+ AfterContentInit
} from '@angular/core';
-
-import {coerceToNumber} from './grid-list';
+import { coerceToNumber } from './grid-list';
+import { MdLine, MdLineSetter } from '@angular2-material/core/line/line';
@Component({
moduleId: module.id,
@@ -19,11 +22,8 @@ import {coerceToNumber} from './grid-list';
export class MdGridTile {
_rowspan: number = 1;
_colspan: number = 1;
- _element: HTMLElement;
- constructor(private _renderer: Renderer, element: ElementRef) {
- this._element = element.nativeElement;
- }
+ constructor(private _renderer: Renderer, private _element: ElementRef) {}
@Input()
get rowspan() {
@@ -48,7 +48,28 @@ export class MdGridTile {
* @internal
*/
setStyle(property: string, value: string): void {
- this._renderer.setElementStyle(this._element, property, value);
+ this._renderer.setElementStyle(this._element.nativeElement, property, value);
}
}
+
+@Component({
+ moduleId: module.id,
+ selector: 'md-grid-tile-header, md-grid-tile-footer',
+ templateUrl: 'grid-tile-text.html'
+})
+export class MdGridTileText implements AfterContentInit {
+ /**
+ * Helper that watches the number of lines in a text area and sets
+ * a class on the host element that matches the line count.
+ */
+ _lineSetter: MdLineSetter;
+ @ContentChildren(MdLine) _lines: QueryList;
+
+ constructor(private _renderer: Renderer, private _element: ElementRef) {}
+
+ ngAfterContentInit() {
+ this._lineSetter = new MdLineSetter(this._lines, this._renderer, this._element);
+ }
+}
+
diff --git a/src/components/list/list.scss b/src/components/list/list.scss
index 9739e9caf597..c93d7c05968a 100644
--- a/src/components/list/list.scss
+++ b/src/components/list/list.scss
@@ -1,5 +1,6 @@
@import "variables";
@import "default-theme";
+@import "list-shared";
$md-list-side-padding: 16px;
$md-list-avatar-size: 40px;
@@ -56,27 +57,12 @@ based on whether the list is in dense mode.
}
.md-list-text {
- display: flex;
- flex-direction: column;
- width: 100%;
+ @include md-line-wrapper-base();
padding: 0 $md-list-side-padding;
- box-sizing: border-box;
- overflow: hidden;
&:first-child {
padding: 0;
}
-
- &:empty {
- display: none;
- }
-
- & > * {
- margin: 0;
- padding: 0;
- font-weight: normal;
- font-size: inherit;
- }
}
[md-list-avatar] {
@@ -93,26 +79,6 @@ based on whether the list is in dense mode.
}
}
-/*
-This mixin provides all md-line styles, changing secondary font size
-based on whether the list is in dense mode.
-*/
-@mixin md-line-base($secondary-font-size) {
-
- [md-line] {
- display: block;
- white-space: nowrap;
- overflow-x: hidden;
- text-overflow: ellipsis;
- box-sizing: border-box;
-
- // all lines but the top line should have smaller text
- &:nth-child(n+2) {
- font-size: $secondary-font-size;
- }
- }
-}
-
/*
This mixin provides all subheader styles, adjusting heights and padding
based on whether the list is in dense mode.
diff --git a/src/components/list/list.ts b/src/components/list/list.ts
index face45060bf8..2e1af7513e60 100644
--- a/src/components/list/list.ts
+++ b/src/components/list/list.ts
@@ -9,8 +9,7 @@ import {
Renderer,
AfterContentInit,
} from '@angular/core';
-
-
+import { MdLine, MdLineSetter } from '../../core/line/line';
@Component({
moduleId: module.id,
@@ -22,10 +21,6 @@ import {
})
export class MdList {}
-/* Need directive for a ContentChildren query in list-item */
-@Directive({ selector: '[md-line]' })
-export class MdLine {}
-
/* Need directive for a ContentChild query in list-item */
@Directive({ selector: '[md-list-avatar]' })
export class MdListAvatar {}
@@ -42,27 +37,25 @@ export class MdListAvatar {}
encapsulation: ViewEncapsulation.None
})
export class MdListItem implements AfterContentInit {
- @ContentChildren(MdLine) _lines: QueryList;
-
/** @internal */
hasFocus: boolean = false;
- /** TODO: internal */
- ngAfterContentInit() {
- this._setLineClass(this._lines.length);
+ _lineSetter: MdLineSetter;
- this._lines.changes.subscribe(() => {
- this._setLineClass(this._lines.length);
- });
- }
+ @ContentChildren(MdLine) _lines: QueryList;
@ContentChild(MdListAvatar)
private set _hasAvatar(avatar: MdListAvatar) {
- this._setClass('md-list-avatar', avatar != null);
+ this._renderer.setElementClass(this._element.nativeElement, 'md-list-avatar', avatar != null);
}
constructor(private _renderer: Renderer, private _element: ElementRef) {}
+ /** TODO: internal */
+ ngAfterContentInit() {
+ this._lineSetter = new MdLineSetter(this._lines, this._renderer, this._element);
+ }
+
/** @internal */
handleFocus() {
this.hasFocus = true;
@@ -72,22 +65,6 @@ export class MdListItem implements AfterContentInit {
handleBlur() {
this.hasFocus = false;
}
-
- private _setLineClass(count: number): void {
- this._resetClasses();
- if (count === 2 || count === 3) {
- this._setClass(`md-${count}-line`, true);
- }
- }
-
- private _resetClasses(): void {
- this._setClass('md-2-line', false);
- this._setClass('md-3-line', false);
- }
-
- private _setClass(className: string, bool: boolean): void {
- this._renderer.setElementClass(this._element.nativeElement, className, bool);
- }
}
export const MD_LIST_DIRECTIVES = [MdList, MdListItem, MdLine, MdListAvatar];
diff --git a/src/core/line/line.ts b/src/core/line/line.ts
new file mode 100644
index 000000000000..90935c125cab
--- /dev/null
+++ b/src/core/line/line.ts
@@ -0,0 +1,44 @@
+import {
+ Directive,
+ Renderer,
+ ElementRef,
+ QueryList
+} from '@angular/core';
+
+/**
+ * Shared directive to count lines inside a text area, such as a list item.
+ * Line elements can be extracted with a @ContentChildren(MdLine) query, then
+ * counted by checking the query list's length.
+ */
+@Directive({ selector: '[md-line]' })
+export class MdLine {}
+
+/* Helper that takes a query list of lines and sets the correct class on the host */
+export class MdLineSetter {
+ constructor(private _lines: QueryList, private _renderer: Renderer,
+ private _element: ElementRef) {
+ this._setLineClass(this._lines.length);
+
+ this._lines.changes.subscribe(() => {
+ this._setLineClass(this._lines.length);
+ });
+ }
+
+
+ private _setLineClass(count: number): void {
+ this._resetClasses();
+ if (count === 2 || count === 3) {
+ this._setClass(`md-${count}-line`, true);
+ }
+ }
+
+ private _resetClasses(): void {
+ this._setClass('md-2-line', false);
+ this._setClass('md-3-line', false);
+ }
+
+ private _setClass(className: string, bool: boolean): void {
+ this._renderer.setElementClass(this._element.nativeElement, className, bool);
+ }
+
+}
diff --git a/src/core/style/_list-shared.scss b/src/core/style/_list-shared.scss
new file mode 100644
index 000000000000..4de8b7edfe87
--- /dev/null
+++ b/src/core/style/_list-shared.scss
@@ -0,0 +1,50 @@
+/**
+ * This mixin provides all md-line styles, changing secondary font size
+ * based on whether the list is in dense mode.
+ */
+@mixin md-line-base($secondary-font-size) {
+ [md-line] {
+ display: block;
+ white-space: nowrap;
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ box-sizing: border-box;
+
+ // all lines but the top line should have smaller text
+ &:nth-child(n+2) {
+ font-size: $secondary-font-size;
+ }
+ }
+}
+
+/**
+ * This mixin provides base styles for the wrapper around md-line
+ * elements in a list.
+ */
+@mixin md-line-wrapper-base() {
+ @include md-normalize-text();
+
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ box-sizing: border-box;
+ overflow: hidden;
+
+ // Must remove wrapper when lines are empty or it takes up horizontal
+ // space and pushes other elements to the right.
+ &:empty {
+ display: none;
+ }
+}
+
+/**
+ * This mixin normalizes default element styles, e.g. font weight for heading text.
+ */
+@mixin md-normalize-text() {
+ & > * {
+ margin: 0;
+ padding: 0;
+ font-weight: normal;
+ font-size: inherit;
+ }
+}
\ No newline at end of file
diff --git a/src/demo-app/grid-list/grid-list-demo.html b/src/demo-app/grid-list/grid-list-demo.html
index 1ddfd2705072..6a915d77f7d1 100644
--- a/src/demo-app/grid-list/grid-list-demo.html
+++ b/src/demo-app/grid-list/grid-list-demo.html
@@ -57,5 +57,35 @@
Change gutter:
+
+
+ Grid list with header
+
+
+
+
+ info_outline
+ {{dog.name}}
+
+
+
+
+
+
+
+ Grid list with footer
+
+
+
+
+
+ {{dog.name}}
+ Human: {{dog.human}}
+ star_border
+
+
+
+
+
diff --git a/src/demo-app/grid-list/grid-list-demo.scss b/src/demo-app/grid-list/grid-list-demo.scss
index 4e6856e6a191..607acef66a07 100644
--- a/src/demo-app/grid-list/grid-list-demo.scss
+++ b/src/demo-app/grid-list/grid-list-demo.scss
@@ -1,5 +1,5 @@
.demo-grid-list {
- width: 800px;
+ width: 1100px;
md-card {
margin: 16px 0;
@@ -12,4 +12,8 @@
.demo-basic-list md-grid-tile {
background: rgba(0,0,0,0.32);
}
+
+ img {
+ width: 350px;
+ }
}
diff --git a/src/demo-app/grid-list/grid-list-demo.ts b/src/demo-app/grid-list/grid-list-demo.ts
index 095d44c3cc9b..bb1ead3ad70b 100644
--- a/src/demo-app/grid-list/grid-list-demo.ts
+++ b/src/demo-app/grid-list/grid-list-demo.ts
@@ -2,13 +2,15 @@ import {Component} from '@angular/core';
import {MD_GRID_LIST_DIRECTIVES} from '@angular2-material/grid-list/grid-list';
import {MdButton} from '@angular2-material/button/button';
import {MD_CARD_DIRECTIVES} from '@angular2-material/card/card';
+import {MdIcon, MdIconRegistry} from '@angular2-material/icon/icon';
@Component({
moduleId: module.id,
selector: 'grid-list-demo',
templateUrl: 'grid-list-demo.html',
styleUrls: ['grid-list-demo.css'],
- directives: [MD_GRID_LIST_DIRECTIVES, MdButton, MD_CARD_DIRECTIVES]
+ directives: [MD_GRID_LIST_DIRECTIVES, MdButton, MD_CARD_DIRECTIVES, MdIcon],
+ providers: [MdIconRegistry]
})
export class GridListDemo {
tiles: any[] = [
@@ -18,6 +20,15 @@ export class GridListDemo {
{text: 'Four', cols: 2, rows: 1, color: '#DDBDF1'},
];
+ dogs: Object[] = [
+ { name: 'Porter', human: 'Kara' },
+ { name: 'Mal', human: 'Jeremy' },
+ { name: 'Koby', human: 'Igor' },
+ { name: 'Razzle', human: 'Ward' },
+ { name: 'Molly', human: 'Rob' },
+ { name: 'Husi', human: 'Matias' },
+ ];
+
fixedCols: number = 4;
fixedRowHeight: number = 100;
ratioGutter: number = 1;