mirror of
https://github.com/koel/koel
synced 2024-11-10 14:44:13 +00:00
Add a "Back to Top" button for long-scrolling pages
This commit is contained in:
parent
35b8c86b06
commit
1751600824
7 changed files with 97 additions and 1 deletions
|
@ -12,6 +12,8 @@
|
|||
| limitBy numOfItems" :album="item"></album-item>
|
||||
|
||||
<span class="item filler" v-for="n in 6"></span>
|
||||
|
||||
<to-top-button :showing="showBackToTop"></to-top-button>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
| limitBy numOfItems" :artist="item"></artist-item>
|
||||
|
||||
<span class="item filler" v-for="n in 6"></span>
|
||||
|
||||
<to-top-button :showing="showBackToTop"></to-top-button>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<span>{{ greeting }}</span>
|
||||
</h1>
|
||||
|
||||
<div class="main-scroll-wrap">
|
||||
<div class="main-scroll-wrap" v-el:wrapper @scroll="scrolling">
|
||||
<div class="top-sections">
|
||||
<section v-show="topSongs.length">
|
||||
<h1>Most Played Songs</h1>
|
||||
|
@ -76,6 +76,8 @@
|
|||
<span class="item filler" v-for="n in 3"></span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<to-top-button :showing="showBackToTop"></to-top-button>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
@ -90,12 +92,18 @@
|
|||
import userStore from '../../../stores/user';
|
||||
import queueStore from '../../../stores/queue';
|
||||
import preferenceStore from '../../../stores/preference';
|
||||
import infiniteScroll from '../../../mixins/infinite-scroll';
|
||||
|
||||
import albumItem from '../../shared/album-item.vue';
|
||||
import artistItem from '../../shared/artist-item.vue';
|
||||
|
||||
export default {
|
||||
components: { albumItem, artistItem },
|
||||
/**
|
||||
* We're not really using infinite scrolling here, but only the handy "Back to Top" button.
|
||||
* @type {Array}
|
||||
*/
|
||||
mixins: [infiniteScroll],
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
|
|
@ -173,5 +173,14 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 375px) {
|
||||
> section {
|
||||
// Leave some space for the "Back to top" button
|
||||
.main-scroll-wrap {
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
</table>
|
||||
|
||||
<song-menu v-ref:context-menu :songs="selectedSongs"></song-menu>
|
||||
<to-top-button :showing="showBackToTop"></to-top-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
58
resources/assets/js/components/shared/to-top-button.vue
Normal file
58
resources/assets/js/components/shared/to-top-button.vue
Normal file
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<div class="to-top-btn-wrapper" v-show="showing" transition="fade">
|
||||
<button @click="$parent.scrollToTop()">
|
||||
<i class="fa fa-arrow-circle-up"></i>
|
||||
Top
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['showing'],
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
@import "../../../sass/partials/_vars.scss";
|
||||
@import "../../../sass/partials/_mixins.scss";
|
||||
|
||||
.to-top-btn-wrapper {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: $footerHeight + 16px;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
z-index: 9999;
|
||||
|
||||
&.fade-transition {
|
||||
opacity: 1;
|
||||
transition: opacity .5s;
|
||||
}
|
||||
|
||||
&.fade-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.fade-leave {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 18px;
|
||||
padding: 8px 16px;
|
||||
background: rgba(0, 0, 0, .5);
|
||||
border: 1px solid $colorMainText;
|
||||
|
||||
i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 376px) {
|
||||
.to-top-btn-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,7 @@
|
|||
import $ from 'jquery';
|
||||
|
||||
import toTopButton from '../components/shared/to-top-button.vue';
|
||||
|
||||
/**
|
||||
* Add a "infinite scroll" functionality to any component using this mixin.
|
||||
* Such a component should:
|
||||
|
@ -8,10 +10,13 @@ import $ from 'jquery';
|
|||
* - have the array of all objects named as `items`, either as data, computed, or a prop
|
||||
*/
|
||||
export default {
|
||||
components: { toTopButton },
|
||||
|
||||
data() {
|
||||
return {
|
||||
numOfItems: 30, // Number of currently loaded and displayed items
|
||||
perPage: 30, // Number of items to be loaded per "page"
|
||||
showBackToTop: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -24,6 +29,8 @@ export default {
|
|||
if ($wrapper.scrollTop() + $wrapper.innerHeight() >= $wrapper[0].scrollHeight - 32) {
|
||||
this.displayMore();
|
||||
}
|
||||
|
||||
this.showBackToTop = $wrapper.scrollTop() > 64;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -32,11 +39,20 @@ export default {
|
|||
displayMore() {
|
||||
this.numOfItems += this.perPage;
|
||||
},
|
||||
|
||||
/**
|
||||
* Scroll to top fo the wrapper.
|
||||
*/
|
||||
scrollToTop() {
|
||||
$(this.$els.wrapper).animate({ scrollTop: 0}, 500);
|
||||
this.showBackToTop = false;
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
'koel:teardown': function () {
|
||||
this.numOfItems = 30;
|
||||
this.showBackToTop = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue