Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 5b84e73

Browse files
authored
feat(grid-list): Implement mdc-grid-list (#47) (#359)
1 parent cc939ea commit 5b84e73

File tree

14 files changed

+1442
-0
lines changed

14 files changed

+1442
-0
lines changed

demos/grid-list.html

Lines changed: 666 additions & 0 deletions
Large diffs are not rendered by default.

demos/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<li><a href="drawer/permanent-drawer-below-toolbar.html">Drawer (permanent, below toolbar)</a></li>
3434
<li><a href="elevation.html">Elevation</a></li>
3535
<li><a href="fab.html">FAB</a></li>
36+
<li><a href="grid-list.html">Grid List</a></li>
3637
<li><a href="icon-toggle.html">Icon Toggle</a></li>
3738
<li><a href="layout-grid.html">Layout grid</a></li>
3839
<li><a href="list.html">List</a></li>

packages/material-components-web/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import * as base from '@material/base';
1818
import * as checkbox from '@material/checkbox';
1919
import * as formField from '@material/form-field';
20+
import * as gridList from '@material/grid-list';
2021
import * as iconToggle from '@material/icon-toggle';
2122
import * as radio from '@material/radio';
2223
import * as ripple from '@material/ripple';
@@ -31,6 +32,7 @@ import autoInit from '@material/auto-init';
3132
autoInit.register('MDCCheckbox', checkbox.MDCCheckbox);
3233
autoInit.register('MDCTemporaryDrawer', drawer.MDCTemporaryDrawer);
3334
autoInit.register('MDCRipple', ripple.MDCRipple);
35+
autoInit.register('MDCGridList', gridList.MDCGridList);
3436
autoInit.register('MDCIconToggle', iconToggle.MDCIconToggle);
3537
autoInit.register('MDCRadio', radio.MDCRadio);
3638
autoInit.register('MDCSnackbar', snackbar.MDCSnackbar);
@@ -43,6 +45,7 @@ export {
4345
base,
4446
checkbox,
4547
formField,
48+
gridList,
4649
iconToggle,
4750
radio,
4851
ripple,

packages/material-components-web/material-components-web.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
@import "@material/elevation/mdc-elevation";
2323
@import "@material/fab/mdc-fab";
2424
@import "@material/form-field/mdc-form-field";
25+
@import "@material/grid-list/mdc-grid-list";
2526
@import "@material/icon-toggle/mdc-icon-toggle";
2627
@import "@material/layout-grid/mdc-layout-grid";
2728
@import "@material/list/mdc-list";

packages/material-components-web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@material/elevation": "^0.1.3",
2424
"@material/fab": "^0.3.3",
2525
"@material/form-field": "^0.2.1",
26+
"@material/grid-list": "^0.0.0",
2627
"@material/icon-toggle": "^0.1.5",
2728
"@material/layout-grid": "^0.1.1",
2829
"@material/list": "^0.2.3",

packages/mdc-grid-list/README.md

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
# MDC Grid list
2+
3+
MDC Grid list provides a RTL-aware Material Design Grid list component adhering to the
4+
[Material Design Grid list spec](https://material.io/guidelines/components/grid-lists.html).
5+
Grid Lists are best suited for presenting homogeneous data, typically images.
6+
Each item in a grid list is called a **tile**. Tiles maintain consistent width, height, and padding
7+
across screen sizes.
8+
9+
10+
## Installation
11+
12+
```
13+
npm install --save @material/grid-list
14+
```
15+
16+
17+
## Usage
18+
19+
Basic Grid list has the following structure:
20+
21+
```html
22+
<div class="mdc-grid-list">
23+
<ul class="mdc-grid-list__tiles">
24+
<li class="mdc-grid-tile">
25+
<div class="mdc-grid-tile__primary">
26+
<img class="mdc-grid-tile__primary-content" src="my-image.jpg" />
27+
</div>
28+
<span class="mdc-grid-tile__secondary">
29+
<span class="mdc-grid-tile__title">Title</span>
30+
</span>
31+
</li>
32+
<li class="mdc-grid-tile">
33+
<div class="mdc-grid-tile__primary">
34+
<img class="mdc-grid-tile__primary-content" src="my-image.jpg" />
35+
</div>
36+
<span class="mdc-grid-tile__secondary">
37+
<span class="mdc-grid-tile__title">Title</span>
38+
</span>
39+
</li>
40+
</ul>
41+
</div>
42+
```
43+
44+
The above markup will give you a Grid list of tiles that:
45+
46+
- Have 4px padding in between themselves
47+
- Have a 1x1 aspect ratio
48+
- Have a one-line footer caption with no icon
49+
50+
You just need to put the content you want to load in `src` of
51+
`<img class="mdc-grid-tile__primary-content" src="..."/>`. However, if your
52+
assets don't have the same aspect ratio you as specified in the tile, it will
53+
distort those assets. We provide a solution of that case in
54+
[Using a div in place of an img](#using-a-div-in-place-of-an-img) section.
55+
56+
57+
### Setting the tile width
58+
59+
The tile width is set to 200px by default. There are three ways that you can
60+
overwrite the default value for your grid list:
61+
62+
1. Using CSS variables
63+
64+
```css
65+
.mdc-grid-tile {
66+
--mdc-grid-list-tile-width: 300px;
67+
}
68+
```
69+
70+
2. Overwriting SCSS variable
71+
72+
You can overwrite the scss variable by
73+
74+
```scss
75+
@import "@material/grid-list/mdc-grid-list";
76+
$mdc-grid-list-tile-width: 300px;
77+
```
78+
79+
3. Add own style to tile
80+
81+
```html
82+
<style>
83+
.my-grid-list .mdc-grid-tile {
84+
width : 300px;
85+
}
86+
</style>
87+
<div class="mdc-grid-list my-grid-list">
88+
<ul class="mdc-grid-list__tiles">
89+
<li class="mdc-grid-tile"></li>
90+
...
91+
</ul>
92+
</div>
93+
```
94+
95+
### Change tile padding
96+
97+
Grid list tiles can have 1px padding instead of 4px by adding
98+
`mdc-grid-list--tile-gutter-1` modifier.
99+
100+
```html
101+
<div class="mdc-grid-list mdc-grid-list--tile-gutter-1">
102+
<ul class="mdc-grid-list__tiles">
103+
...
104+
</ul>
105+
</div>
106+
```
107+
108+
### Image only tile
109+
110+
Grid lists support image only tile. You can remove `mdc-grid-tile__secondary`
111+
and create a image only grid list.
112+
113+
```html
114+
<div class="mdc-grid-list mdc-grid-list--tile-gutter-1">
115+
<ul class="mdc-grid-list__tiles">
116+
<li class="mdc-grid-tile">
117+
<div class="mdc-grid-tile__primary">
118+
<img class="mdc-grid-tile__primary-content" src="images/1-1.jpg" />
119+
</div>
120+
</li>
121+
</ul>
122+
</div>
123+
```
124+
125+
### Header caption
126+
127+
Grid lists support header caption. You can change the footer caption to be a
128+
header caption by adding `mdc-grid-list--header-caption` modifier.
129+
130+
```html
131+
<div class="mdc-grid-list mdc-grid-list--header-caption">
132+
<ul class="mdc-grid-list__tiles">
133+
...
134+
</ul>
135+
</div>
136+
```
137+
138+
### Add support text to secondary content (caption)
139+
140+
Grid lists support a one-line caption by default. You can add an additional line of support
141+
text if needed by adding the `mdc-grid-list--twoline-caption` modifier and additional
142+
markup
143+
144+
```html
145+
<div class="mdc-grid-list mdc-grid-list--twoline-caption">
146+
<ul class="mdc-grid-list__tiles">
147+
<li class="mdc-grid-tile">
148+
<div class="mdc-grid-tile__primary">
149+
<img class="mdc-grid-tile__primary-content" src="my-image.jpg" />
150+
</div>
151+
<span class="mdc-grid-tile__secondary">
152+
<span class="mdc-grid-tile__title">Title</span>
153+
<span class="mdc-grid-tile__support-text">Support text</span>
154+
</span>
155+
</li>
156+
</ul>
157+
</div>
158+
```
159+
160+
### Add icon to secondary content (caption)
161+
162+
You can add an icon to a caption by adding `mdc-grid-list--with-icon-align-start` or
163+
`mdc-grid-list--with-icon-align-end` and changing the markup.
164+
165+
```html
166+
<div class="mdc-grid-list mdc-grid-list--with-icon-align-start">
167+
<ul class="mdc-grid-list__tiles">
168+
<li class="mdc-grid-tile">
169+
<div class="mdc-grid-tile__primary">
170+
<img class="mdc-grid-tile__primary-content" src="my-image.jpg" />
171+
</div>
172+
<span class="mdc-grid-tile__secondary">
173+
<i class="mdc-grid-tile__icon material-icons">star_border</i>
174+
<span class="mdc-grid-tile__title">Title</span>
175+
</span>
176+
</li>
177+
</ul>
178+
</div>
179+
```
180+
181+
### Change aspect ratio of tile
182+
183+
Grid list tiles support all material guideline recommended aspect ratio:
184+
185+
- 1x1
186+
- 16x9
187+
- 2x3
188+
- 3x2
189+
- 4x3
190+
- 3x4
191+
192+
You can use the modifier class `mdc-grid-list--tile-aspect-$ASPECT_RATIO` to apply these aspect
193+
ratios to your grid list. Simply replace `$ASPECT_RATIO` with any of the predefined ratios.
194+
195+
```html
196+
<!-- Example of 16x9 tile -->
197+
<div class="mdc-grid-list mdc-grid-list--tile-aspect-16x9">
198+
<ul class="mdc-grid-list__tiles">
199+
...
200+
</ul>
201+
</div>
202+
```
203+
204+
As pointed out in the previous section, if your
205+
assets don't have the same aspect ratio you as specified in the tile, it will
206+
distort those assets. We provide a solution of that case in
207+
[Using a div in place of an img](#using-a-div-in-place-of-an-img) section.
208+
209+
### Using a div in place of an img
210+
211+
In case you cannot ensure all your assets will have the same aspect ratio, you
212+
can use `div` instead of `img` markup. It will resize the assets to cover the tile
213+
and crop the assets to display the center part.
214+
215+
```html
216+
<style>
217+
.my-tile-image {
218+
background-image: url(my-image.jpg);
219+
}
220+
</style>
221+
<div class="mdc-grid-list">
222+
<ul class="mdc-grid-list__tiles">
223+
<li class="mdc-grid-tile">
224+
<div class="mdc-grid-tile__primary">
225+
<div class="mdc-grid-tile__primary-content my-tile-image"></div>
226+
</div>
227+
<span class="mdc-grid-tile__secondary">
228+
<span class="mdc-grid-tile__title">Title</span>
229+
</span>
230+
</li>
231+
</ul>
232+
</div>
233+
```
234+
235+
However, the method results in a less semantic markup, so we don't use this method by
236+
default.
237+
238+
239+
### RTL Support
240+
241+
`mdc-grid-list` is automatically RTL-aware, and will re-position elements whenever
242+
it, or its ancestors, have a `dir="rtl"` attribute.
243+
244+
245+
### Theme
246+
247+
`mdc-grid-list` supports theming. `mdc-grid-tile__primary` uses the theme's background
248+
color for its background color. `mdc-grid-tile__secondary` uses the theme's primary
249+
color for it's background color, and the theme's `text-primary-on-primary` color for its text color.
250+
251+
### Using the Foundation Class
252+
253+
MDCGridList ships with an `MDCGridListFoundation` class that external frameworks and libraries
254+
can use to build their own MDCGridList components with minimal effort. As with all foundation
255+
classes, an adapter object must be provided. The adapter for Grid list must provide the following
256+
functions, with correct signatures:
257+
258+
| Method Signature | Description |
259+
| --- | --- |
260+
| `getOffsetWidth() => number` | Get root element `mdc-grid-list` offsetWidth. |
261+
| `getOffsetWidthForTileAtIndex(index: number) => number` | Get offsetWidth of `mdc-grid-tile` at specified index. |
262+
| `setStyleForTilesElement(property: string, value: number) => void` | Set `mdc-grid-list__tiles` style property to provided value. |
263+
| `registerResizeHandler(handler: Function) => void` | Registers a handler to be called when the surface (or its viewport) resizes. Our default implementation adds the handler as a listener to the window's `resize()` event. |
264+
| `deregisterResizeHandler(handler: Function) => void` | Unregisters a handler to be called when the surface (or its viewport) resizes. Our default implementation removes the handler as a listener to the window's `resize()` event. |

packages/mdc-grid-list/constants.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
export const strings = {
17+
TILES_SELECTOR: '.mdc-grid-list__tiles',
18+
TILE_SELECTOR: '.mdc-grid-tile',
19+
};

packages/mdc-grid-list/foundation.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {MDCFoundation} from '@material/base';
18+
import {strings} from './constants';
19+
20+
export default class MDCGridListFoundation extends MDCFoundation {
21+
static get strings() {
22+
return strings;
23+
}
24+
25+
static get defaultAdapter() {
26+
return {
27+
getOffsetWidth: () => /* number */ 0,
28+
getOffsetWidthForTileAtIndex: (/* index: number */) => /* number */ 0,
29+
setStyleForTilesElement: (/* property: string, value: string */) => {},
30+
registerResizeHandler: (/* handler: EventListener */) => {},
31+
deregisterResizeHandler: (/* handler: EventListener */) => {},
32+
};
33+
}
34+
constructor(adapter) {
35+
super(Object.assign(MDCGridListFoundation.defaultAdapter, adapter));
36+
this.resizeHandler_ = () => this.alignCenter();
37+
this.resizeFrame_ = 0;
38+
}
39+
init() {
40+
this.alignCenter();
41+
this.adapter_.registerResizeHandler(this.resizeHandler_);
42+
}
43+
destroy() {
44+
this.adapter_.deregisterResizeHandler(this.resizeHandler_);
45+
}
46+
alignCenter() {
47+
if (this.resizeFrame_ !== 0) {
48+
cancelAnimationFrame(this.resizeFrame_);
49+
}
50+
this.resizeFrame_ = requestAnimationFrame(() => {
51+
this.alignCenter_();
52+
this.resizeFrame_ = 0;
53+
});
54+
}
55+
alignCenter_() {
56+
const gridWidth = this.adapter_.getOffsetWidth();
57+
const itemWidth = this.adapter_.getOffsetWidthForTileAtIndex(0);
58+
const tilesWidth = itemWidth * Math.floor(gridWidth / itemWidth);
59+
this.adapter_.setStyleForTilesElement('width', `${tilesWidth}px`);
60+
}
61+
}

0 commit comments

Comments
 (0)