Vue
by leonsaysHi
HTML
<div class="wrapper" id="app">
<dashboard-grid :items="items" :focus="focus">
<template v-slot:items>
<div
v-for="(item, idx) in items"
:key="idx"
@click="handleSelect(item)"
class="item"
>{{ item.id }}</div>
</template>
<template v-slot:articles>
<div
v-if="focus"
@click="focus=null"
>Focus {{ focus.id }}</div>
</template>
</dashboard-grid>
</div>
CSS
.wrapper {
margin: 5rem 3rem;
}
.container {
display: grid;
margin: 0 -0.5rem;
}
.item {
height: 150px;
margin: .5rem;
padding: 1rem;
border: solid 1px grey;
border-radius: .2rem;
}
.focus {
height: auto;
background: pink;
}
Vue
Vue.component('dashboard-grid', {
template: '<div><button @click="columns = 1">1</button><button @click="columns = 3">3</button><button @click="columns = 5">5</button><div class="container" :style="containerStyle"><slot name="items"/><div v-if="focus" class="item focus" :style="focusStyle"><slot name="articles"/></div></div></div>',
props: {
items: { type: Array, required: true },
focus: { type: Object, default: null}
},
data() {
return {
columns: 5,
}
},
computed:{
containerStyle() {
return "grid-template-columns: repeat(" + this.columns + ", 1fr);"
},
focusStyle() {
const res = []
if (this.focus) {
res.push("grid-column-start: " + this.columns)
res.push("grid-column-end: span 1")
const row = Math.floor(this.items.findIndex(i => this.focus.id === i.id) / this.columns) + 1
res.push("grid-row-start: " + row)
res.push("grid-row-end: span 2")
}
return res.join(";")
}
}
})
new Vue({
el: "#app",
components: { },
data() {
return {
focus: null,
items: [
{ id:1 },
{ id:2 },
{ id:3 },
{ id:4 },
{ id:5 },
{ id:6 },
{ id:7 },
{ id:8 },
{ id:9 },
]
}
},
computed: {
},
methods: {
handleSelect(item){
this.focus = item
}
}
});