Add sort buttons with ripple effect

This commit is contained in:
Marcos Moura 2016-10-27 03:52:58 -02:00
parent c34a63b672
commit ca83e3b16e
8 changed files with 210 additions and 37 deletions

View file

@ -14,22 +14,23 @@
</md-button>
</md-toolbar>
<md-table md-row-selection>
<md-table md-row-selection md-sort="calories">
<thead>
<md-table-row>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
<th>Head 4</th>
<md-table-head md-sort-by="dessert">Dessert (100g serving)</md-table-head>
<md-table-head md-sort-by="calories" md-numeric>Calories (g)</md-table-head>
<md-table-head md-sort-by="fat" md-numeric>Fat (g)</md-table-head>
<md-table-head md-sort-by="carbs" md-numeric>Carbs (g)</md-table-head>
<md-table-head md-sort-by="protein" md-numeric>Protein (g)</md-table-head>
<md-table-head md-sort-by="sodium" md-numeric>Sodium (mg)</md-table-head>
<md-table-head md-sort-by="calcium" md-numeric>Calcium (%)</md-table-head>
<md-table-head md-sort-by="iron" md-numeric>Iron (%)</md-table-head>
</md-table-row>
</thead>
<tbody>
<md-table-row v-for="test in 100">
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
<md-table-row v-for="(row, index) in 10" :key="index">
<md-table-cell v-for="(col, index) in 8" :key="index" :md-numeric="index > 0">Cell</md-table-cell>
</md-table-row>
</tbody>
</md-table>

View file

@ -1,11 +1,15 @@
import mdTable from './mdTable.vue';
import mdTableCard from './mdTableCard.vue';
import mdTableHead from './mdTableHead.vue';
import mdTableCell from './mdTableCell.vue';
import mdTableRow from './mdTableRow.vue';
import mdTableTheme from './mdTable.theme';
export default function install(Vue) {
Vue.component('md-table', Vue.extend(mdTable));
Vue.component('md-table-card', Vue.extend(mdTableCard));
Vue.component('md-table-head', Vue.extend(mdTableHead));
Vue.component('md-table-cell', Vue.extend(mdTableCell));
Vue.component('md-table-row', Vue.extend(mdTableRow));
Vue.material.styles.push(mdTableTheme);

View file

@ -18,34 +18,21 @@
border-collapse: collapse;
}
tr {
transition: $swift-ease-out;
}
tbody tr {
border-top: 1px solid #e0e0e0;
&:hover {
background-color: #eee;
}
&.md-selected {
&.md-selected .md-table-cell {
background-color: #f5f5f5;
}
}
th,
td {
padding-right: 32px;
padding-left: 24px;
&:last-child {
padding-right: 24px;
&:hover .md-table-cell {
background-color: #eee;
}
}
th {
.md-table-head {
height: 56px;
padding: 0;
position: relative;
overflow: hidden;
color: rgba(#000, .54);
@ -54,20 +41,113 @@
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
&:last-child .md-table-head-container {
padding-right: 24px;
}
}
td {
.md-table-head-container {
height: 100%;
padding-right: 32px;
padding-left: 24px;
display: flex;
align-items: center;
transition: $swift-ease-out;
}
.md-sortable {
cursor: pointer;
&:first-of-type {
.md-icon {
left: auto;
right: 10px;
}
}
&:hover,
&.md-sorted {
.md-icon {
opacity: 1;
}
}
&:hover {
color: rgba(#000, .87);
}
&.md-sorted {
.md-icon {
color: rgba(#000, .87);
}
}
&.md-sorted-descending {
.md-icon {
transform: translateY(-50%) rotate(180deg);
}
}
.md-icon {
$size: 16px;
width: $size;
min-width: $size;
height: $size;
min-height: $size;
position: absolute;
top: 50%;
left: 2px;
transition: $swift-ease-out;
transform: translateY(-50%);
opacity: 0;
color: rgba(#000, .38);
font-size: $size;
}
.md-ink-ripple {
color: rgba(#000, .87);
}
}
.md-table-cell {
height: 48px;
transition: $swift-ease-out;
color: rgba(#000, .87);
font-size: 13px;
line-height: 18px;
&:last-child .md-table-cell-container {
padding-right: 24px;
}
.md-table-cell-container {
padding: 0 24px 0 32px;
}
&.md-numeric {
text-align: right;
}
}
.md-table-selection {
width: 20px;
padding-right: 0;
position: relative;
vertical-align: middle;
+ {
.md-table-cell .md-table-cell-container,
.md-table-head .md-table-head-container {
padding-left: 8px;
}
}
.md-table-cell-container {
padding-right: 16px;
padding-left: 24px;
}
.md-checkbox {
margin: 3px 0 0;
}

View file

@ -11,10 +11,14 @@
<script>
export default {
props: {
mdRowSelection: Boolean
mdRowSelection: Boolean,
mdSortType: String,
mdSort: String
},
data() {
return {
sortType: this.mdSortType,
sortBy: this.mdSort,
numberOfRows: 0,
numberOfSelected: 0,
selectedRows: {}
@ -28,7 +32,10 @@
}
},
methods: {
emitSort(name) {
this.sortBy = name;
this.$emit('sort', name);
}
},
mounted() {

View file

@ -1,5 +1,5 @@
<template>
<md-card class="md-table-card">
<md-card class="md-table-card" v-once>
<slot></slot>
</md-card>
</template>

View file

@ -0,0 +1,22 @@
<template>
<td class="md-table-cell" :class="classes">
<div class="md-table-cell-container">
<slot></slot>
</div>
</td>
</template>
<script>
export default {
props: {
mdNumeric: Boolean
},
computed: {
classes() {
return {
'md-numeric': this.mdNumeric
};
}
}
};
</script>

View file

@ -0,0 +1,57 @@
<template>
<th class="md-table-head" :class="classes" @click="changeSort">
<div class="md-table-head-container" v-md-ink-ripple="!mdSortBy">
<md-icon v-if="mdSortBy">arrow_downward</md-icon>
<span>
<slot></slot>
</span>
</div>
</th>
</template>
<script>
export default {
props: {
mdNumeric: Boolean,
mdSortBy: String
},
data() {
return {
sortType: null,
sorted: false
};
},
computed: {
classes() {
let matchSort = this.$parent.$parent.sortBy === this.mdSortBy;
if (!matchSort) {
this.sorted = false;
}
return {
'md-sortable': this.mdSortBy,
'md-sorted': matchSort && this.sorted,
'md-sorted-descending': matchSort && this.sortType === 'desc'
};
}
},
methods: {
changeSort() {
let parent = this.$parent.$parent;
if (this.sortType === 'asc' && this.sorted) {
this.sortType = 'desc';
} else {
this.sortType = 'asc';
}
this.sorted = true;
parent.sortType = this.sortType;
parent.emitSort(this.mdSortBy);
}
}
};
</script>

View file

@ -1,8 +1,8 @@
<template>
<tr class="md-table-row" :class="classes">
<td class="md-table-selection" v-if="$parent.mdRowSelection">
<md-table-cell class="md-table-selection" v-if="$parent.mdRowSelection">
<md-checkbox v-model="checkbox" @change="select"></md-checkbox>
</td>
</md-table-cell>
<slot></slot>
</tr>
@ -37,10 +37,12 @@
},
handleSingleSelection(value) {
this.setSelectedRow(value, this.index);
this.$parent.$children[0].checkbox = this.$parent.numberOfSelected >= this.$parent.numberOfRows;
this.$parent.$children[0].checkbox = this.$parent.numberOfSelected === this.$parent.numberOfRows;
},
handleMultipleSelection(value) {
this.$parent.$el.classList.add(transitionClass);
if (this.$parent.numberOfRows > 25) {
this.$parent.$el.classList.add(transitionClass);
}
this.$parent.$children.forEach((row) => {
row.checkbox = value;