Create expansible lists

This commit is contained in:
Marcos Moura 2016-09-25 00:15:53 -03:00
parent 3221af9e37
commit 7bcaeabf1d
7 changed files with 246 additions and 22 deletions

View file

@ -31,10 +31,10 @@
"babel-runtime": "^6.11.6",
"connect-history-api-fallback": "^1.3.0",
"css-loader": "^0.25.0",
"eslint": "^3.5.0",
"eslint": "^3.6.0",
"eslint-friendly-formatter": "^2.0.6",
"eslint-loader": "^1.5.0",
"eslint-plugin-html": "^1.5.2",
"eslint-plugin-html": "^1.5.3",
"eventsource-polyfill": "^0.9.6",
"express": "^4.14.0",
"extract-text-webpack-plugin": "^1.0.1",
@ -49,15 +49,15 @@
"sass-loader": "^4.0.2",
"shelljs": "^0.7.4",
"url-loader": "^0.5.7",
"vue": "^2.0.0-rc.5",
"vue": "^2.0.0-rc.7",
"vue-hot-reload-api": "^2.0.6",
"vue-html-loader": "^1.2.3",
"vue-loader": "^9.3.2",
"vue-router": "^2.0.0-rc.4",
"vue-style-loader": "^1.0.0",
"vue-template-compiler": "^2.0.0-rc.6",
"vue-template-compiler": "^2.0.0-rc.7",
"webpack": "^1.13.1",
"webpack-dev-middleware": "^1.7.0",
"webpack-dev-middleware": "^1.8.2",
"webpack-hot-middleware": "^2.12.2",
"webpack-merge": "^0.14.1"
}

View file

@ -1,10 +1,12 @@
import mdList from './mdList.vue';
import mdListItem from './mdListItem.vue';
import mdListExpand from './mdListExpand.vue';
import mdListTheme from './mdList.theme';
export default function install(Vue) {
Vue.component('md-list', Vue.extend(mdList));
Vue.component('md-list-item', Vue.extend(mdListItem));
Vue.component('md-list-expand', Vue.extend(mdListExpand));
window.VueMaterial.styles.push(mdListTheme);
}

View file

@ -12,13 +12,12 @@
padding: 4px 0;
.md-list-item {
min-height: 40px;
&.md-inset .md-list-item-container {
padding-left: 72px;
}
.md-list-item-container {
min-height: 40px;
font-size: 13px;
.md-avatar:first-child {
@ -38,7 +37,9 @@
&.md-double-line {
&.md-dense {
.md-list-item {
min-height: 60px;
.md-list-item-container {
min-height: 60px;
}
.md-avatar {
width: 36px;
@ -64,14 +65,18 @@
}
.md-list-item {
min-height: 72px;
.md-list-item-container {
min-height: 72px;
}
}
}
&.md-triple-line {
&.md-dense {
.md-list-item {
min-height: 76px;
.md-list-item-container {
min-height: 76px;
}
.md-avatar {
width: 36px;
@ -97,7 +102,9 @@
}
.md-list-item {
min-height: 88px;
.md-list-item-container {
min-height: 88px;
}
}
.md-avatar {
@ -122,8 +129,6 @@
.md-list-item {
height: auto;
min-height: 48px;
display: flex;
position: relative;
&.md-inset {
@ -134,14 +139,13 @@
.md-list-item-container {
width: 100%;
min-height: 0;
min-height: 48px;
margin: 0;
padding: 0 16px;
display: flex;
position: relative;
flex: 1 1 auto;
flex-flow: row nowrap;
align-items: center;
position: relative;
border-radius: 0;
font-size: 16px;
font-weight: 400;
@ -195,6 +199,76 @@
}
}
.md-list-item-expand {
min-height: 48px;
flex-flow: column wrap;
overflow: hidden;
&:before,
&:after {
height: 1px;
position: absolute;
right: 0;
left: 0;
z-index: 3;
transition: $swift-ease-out;
content: " ";
}
&:before {
top: 0;
}
&:after {
bottom: 0;
}
&.md-active {
position: relative;
&:before,
&:after {
background-color: rgba(#000, .12);
}
&:first-of-type {
&:before {
background: none;
}
}
.md-list-expand-indicator {
transform: rotateZ(180deg) translate3D(0, 0, 0);
}
.md-list-expand {
margin-bottom: 0 !important;
}
}
> .md-list-item-container {
position: relative;
z-index: 2;
}
.md-expansion-indicator,
.md-list-item-container,
.md-icon {
transition: $swift-ease-out;
}
.md-list-expand {
position: relative;
z-index: 1;
transform: translate3D(0, 0, 0);
transition: $swift-ease-out;
&.md-transition-off {
transition: none;
}
}
}
.md-list-text-container {
display: flex;
flex-flow: column nowrap;

View file

@ -48,5 +48,24 @@
}
}
}
.md-list-item-expand {
&.md-active {
color: #{'PRIMARY-COLOR'};
.md-icon:not(.md-list-expand-indicator) {
color: #{'PRIMARY-COLOR'};
}
}
.md-list-item-container {
background-color: #{'BACKGROUND-COLOR-A100'};
&:hover,
&:focus {
background-color: rgba(#999, .2);
}
}
}
}
}

View file

@ -0,0 +1,23 @@
<template>
<div class="md-list-expand" :style="{ 'margin-bottom': height }">
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {
height: null
};
},
watch: {
'$el.offsetHeight': function() {
console.log(this);
}
},
mounted() {
this.height = -this.$el.offsetHeight + 'px';
}
};
</script>

View file

@ -2,8 +2,6 @@
export default {
props: {
href: String,
vLink: [String, Object],
title: String,
target: String
},
render(createElement) {
@ -28,15 +26,70 @@
return createElement('li', listItem, slot);
}
let expand;
let expandIndex;
slot.some((slot, index) => {
if (slot.componentOptions && slot.componentOptions.tag === 'md-list-expand') {
expand = slot;
expandIndex = index;
return true;
}
});
if (expand) {
let expandArrow = createElement('md-icon', {
staticClass: 'md-list-expand-indicator'
}, 'keyboard_arrow_down');
slot.splice(expandIndex, 1);
slot.push(expandArrow);
let container = createElement('div', {
staticClass: containerClass,
on: {
click: () => {
let target;
this.$parent.$children.some((child) => {
if (child.$el.classList.contains('md-list-item-expand') && child.$el.classList.contains('md-active')) {
target = child;
child.$el.classList.remove('md-active');
return true;
}
});
if (!target || this.$el !== target.$el) {
this.$el.classList.add('md-active');
}
this.$emit('click');
}
},
directives: [{
name: 'md-ink-ripple'
}]
}, slot);
listItem.staticClass += ' md-list-item-expand';
return createElement('li', listItem, [container, expand]);
}
let button = createElement('md-button', {
staticClass: containerClass,
attrs: {
title: this.title,
target: this.target,
href: this.href
}
}, slot);
if (this.target) {
button.data.attrs.rel = 'noopener';
}
return createElement('li', listItem, [button]);
}
};

View file

@ -9,7 +9,7 @@
</md-list-item>
<md-list-item>
<md-icon>send</md-icon> <span>Outbox</span>
<md-icon>send</md-icon> <span>Sent Mail</span>
</md-list-item>
<md-list-item>
@ -67,7 +67,7 @@
</md-list-item>
<md-list-item>
<md-icon>send</md-icon> <span>Outbox</span>
<md-icon>send</md-icon> <span>Sent Mail</span>
</md-list-item>
<md-list-item>
@ -367,6 +367,58 @@
</div>
</demo-example>
<demo-example label="Controls">
<div class="phone-viewport">
<md-list>
<md-list-item>
<md-icon>whatshot</md-icon>
<span>News</span>
<md-list-expand>
<md-list>
<md-list-item class="md-inset">World</md-list-item>
<md-list-item class="md-inset">Americas</md-list-item>
<md-list-item class="md-inset">Europe</md-list-item>
</md-list>
</md-list-expand>
</md-list-item>
<md-list-item>
<md-icon>videogame_asset</md-icon>
<span>Games</span>
<md-list-expand>
<md-list>
<md-list-item class="md-inset">Console</md-list-item>
<md-list-item class="md-inset">PC</md-list-item>
<md-list-item class="md-inset">Phone</md-list-item>
</md-list>
</md-list-expand>
</md-list-item>
<md-list-item>
<md-icon>video_library</md-icon>
<span>Video</span>
<md-list-expand>
<md-list>
<md-list-item class="md-inset">Humor</md-list-item>
<md-list-item class="md-inset">Music</md-list-item>
<md-list-item class="md-inset" @click="test = !test">Movies</md-list-item>
<md-list-item class="md-inset">TV Shows</md-list-item>
<md-list-item class="md-inset" v-if="test">Test</md-list-item>
</md-list>
</md-list-expand>
</md-list-item>
<md-list-item>
<md-icon>shopping_basket</md-icon>
<span>Shop</span>
</md-list-item>
</md-list>
</div>
</demo-example>
<demo-example label="Complete Example">
<div class="phone-viewport complete-example">
<md-whiteframe md-elevation="3">
@ -664,7 +716,8 @@
export default {
data() {
return {
sidenavVisible: false
sidenavVisible: false,
test: false
};
},
methods: {