Added loading placeholders

This commit is contained in:
Roman Cervantes 2019-01-11 13:20:21 -07:00
parent 1bcd18715a
commit dd0936c272
8 changed files with 1072 additions and 1063 deletions

View file

@ -0,0 +1,88 @@
<template lang="html">
<div class="gameboard-placeholder">
<div class="list" v-for="list in lists" :key="list.name">
<div class="list-header" />
<div class="games">
<div class="game">
<placeholder
image
v-for="n in list.games.length"
:lines="2"
:key="n"
/>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
import Placeholder from '@/components/Placeholder/Placeholder';
export default {
components: {
Placeholder,
},
computed: {
...mapState(['gameLists', 'platform']),
lists() {
return this.gameLists && this.gameLists[this.platform.code]
? this.gameLists[this.platform.code]
: null;
},
},
methods: {
randomColumn() {
return Math.floor(Math.random() * 4) + 1;
},
},
};
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "~styles/styles.scss";
.gameboard-placeholder {
user-select: none;
display: flex;
align-items: flex-start;
}
.list {
flex-shrink: 0;
cursor: default;
border-radius: $border-radius;
background: $color-white;
overflow: hidden;
position: relative;
width: $list-width;
margin-right: $gp;
max-height: calc(100vh - 81px);
.list-header {
background: $color-dark-gray;
height: $list-header-height;
position: absolute;
width: 100%;
}
.games {
margin-top: $list-header-height;
width: 100%;
padding: $gp / 2;
.game {
.placeholder {
padding-right: $gp;
background: $color-white;
margin-bottom: $gp / 2;
}
}
}
}
</style>

View file

@ -0,0 +1,110 @@
<template lang="html">
<div>
<div class="game-detail">
<div class="game-hero" />
<div class="game-detail-container">
<div class="game-info">
<placeholder image large />
<div>
<placeholder :lines="1" large class="title" />
<placeholder :lines="5" class="description" />
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Placeholder from '@/components/Placeholder/Placeholder';
export default {
components: {
Placeholder,
},
};
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "~styles/styles.scss";
.game-detail {
display: flex;
justify-content: center;
background: $color-light-gray;
min-height: calc(100vh - #{$navHeight});
@media($small) {
margin: 0;
}
&.dark {
.game-detail-container {
background: #333;
color: $color-gray;
}
}
}
.game-hero {
background-color: $color-dark-gray;
position: absolute;
width: 100%;
left: 0;
height: 400px;
z-index: 1;
@media($small) {
background: none !important;
}
}
.game-info {
display: grid;
grid-template-columns: 180px auto;
grid-gap: $gp * 2;
margin: 0 $gp;
@media($small) {
grid-gap: 0;
grid-template-columns: 1fr;
text-align: center;
.game-description {
text-align: justify;
}
}
.game-description {
line-height: 1.4rem;
}
}
.game-detail-container {
background-color: rgba(255, 255, 255, 0.95);
-webkit-box-shadow: 0 0 2px 0 $color-gray;
box-shadow: 0 0 2px 0 $color-gray;
width: $container-width;
max-width: 100%;
z-index: 1;
margin: 100px;
padding: $gp 0;
border-radius: $border-radius;
.title {
width: 50%;
}
.description {
width: 75%;
}
@media($small) {
margin: 0;
border-radius: 0;
}
}
</style>

View file

@ -0,0 +1,86 @@
<template lang="html">
<div class="placeholder" :class="{ 'has-image': image, large }" v-if="image || lines">
<div class="image" v-if="image" />
<div class="text" v-if="lines">
<div
class="text-line"
v-for="n in lines"
:key="n"
/>
</div>
</div>
</template>
<script>
export default {
props: {
image: Boolean,
large: Boolean,
lines: Number,
},
};
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "~styles/styles.scss";
.placeholder {
max-width: 100%;
&.has-image {
display: grid;
grid-template-columns: 80px auto;
grid-gap: $gp;
}
}
// Animation
@keyframes placeholder{
0%{
background-position: -468px 0
}
100%{
background-position: 468px 0
}
}
.animated-background {
animation-duration: 1s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: placeholder;
animation-timing-function: linear;
background: $color-light-gray;
background: linear-gradient(to right,
$color-light-gray 8%,
#F0F0F0 18%, $color-light-gray 33%);
background-size: 800px 104px;
height: 96px;
position: relative;
}
.image {
height: 120px;
width: 80px;
@extend .animated-background;
}
.text-line {
height: 12px;
width: 100%;
margin-bottom: $gp / 2;
@extend .animated-background;
}
.large {
.text-line {
height: 30px;
}
.image {
height: 220px;
width: 175px;
}
}
</style>

View file

@ -7,14 +7,7 @@
:class="{ dark: darkModeEnabled, 'drag-scroll-active': dragScrollActive }"
v-dragscroll:nochilddrag
>
<template v-if="loading">
Loading...
</template>
<!-- <div v-else-if="!gameLists[platform.code]">
// TODO: SHOW FTU
Boom
</div> -->
<game-board-placeholder v-if="loading" />
<template>
<list
@ -22,7 +15,7 @@
:games="list.games"
:listIndex="listIndex"
:key="`${list.name}-${listIndex}`"
v-if="list"
v-if="list && !loading"
v-for="(list, listIndex) in gameLists[platform.code]"
@end="dragEnd"
@remove="tryDelete(listIndex)"
@ -39,6 +32,7 @@
<script>
import { dragscroll } from 'vue-dragscroll';
import AddList from '@/components/Lists/AddList';
import GameBoardPlaceholder from '@/components/GameBoard/GameBoardPlaceholder';
import Panel from '@/components/Panel/Panel';
import { $success, $error, swal } from '@/shared/modals';
import List from '@/components/GameBoard/List';
@ -58,6 +52,7 @@ export default {
draggable,
List,
AddList,
GameBoardPlaceholder,
Panel,
},
@ -210,7 +205,7 @@ export default {
.panel {
margin-right: $gp;
width: 300px;
width: $list-width;
}
.lists {

View file

@ -1,6 +1,9 @@
<template lang="html">
<!-- eslint-disable -->
<div class="game-detail" v-if="game" :class="{ dark: darkModeEnabled }">
<div>
<game-detail-placeholder v-if="!game" />
<div class="game-detail" v-else :class="{ dark: darkModeEnabled }">
<div class="game-hero" :style="style" />
<div class="game-detail-container">
@ -45,6 +48,7 @@
</div>
</div>
</div>
</div>
</template>
<script>
@ -55,6 +59,7 @@ import GameScreenshots from '@/components/GameDetail/GameScreenshots';
import GameVideos from '@/components/GameDetail/GameVideos';
import GameReviewBox from '@/components/GameDetail/GameReviewBox';
import AffiliateLink from '@/components/GameDetail/AffiliateLink';
import GameDetailPlaceholder from '@/components/GameDetail/GameDetailPlaceholder';
export default {
components: {
@ -63,6 +68,7 @@ export default {
GameVideos,
GameReviewBox,
AffiliateLink,
GameDetailPlaceholder,
},
computed: {

View file

@ -1,6 +1,6 @@
<template lang="html">
<main v-dragscroll:nochilddrag>
<span v-if="loading">Loading...</span>
<game-board-placeholder v-if="loading" />
<section
v-if="!loading && listData && publicGameData"
@ -9,11 +9,9 @@
>
<header>{{ list.name }} ({{ list.games.length }})</header>
<div class="empty-list" v-if="!list.games.length">
<h3>This collection is empty</h3>
</div>
<div class="games">
<p v-if="!list.games.length">This list is empty</p>
<div class="games" v-else>
<div
v-if="publicGameData[game]"
class="game-card"
@ -35,6 +33,7 @@
<script>
import firebase from 'firebase/app';
import GameBoardPlaceholder from '@/components/GameBoard/GameBoardPlaceholder';
import { swal } from '@/shared/modals';
import { dragscroll } from 'vue-dragscroll';
import { mapState } from 'vuex';
@ -48,6 +47,10 @@ db.settings({
});
export default {
components: {
GameBoardPlaceholder,
},
directives: {
dragscroll,
},

View file

@ -3,6 +3,7 @@ $gp: 16px;
$navHeight: 48px;
$container-width: 900px;
$list-header-height: 30px;
$list-width: 300px;
// Media queries
$small: "max-width: 780px";

1742
yarn.lock

File diff suppressed because it is too large Load diff