mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 12:33:03 +00:00
Introduce tabs to right sidebar
- new icons - rename upnext.vue to queue.vue - other tiny changes
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div class="r-home image">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.r-home {
|
||||
height: 100%;
|
||||
width: 31rem;
|
||||
background-image: url("https://pro2-bar-s3-cdn-cf2.myportfolio.com/a534e2586a621751e93466e77f5228be/d686c78b-9cd7-4eeb-a660-69cfaf7e4cac_rw_600.gif");
|
||||
color: transparent;
|
||||
}
|
||||
</style>
|
||||
@@ -1,20 +1,25 @@
|
||||
<template>
|
||||
<div class="r-sidebar">
|
||||
<!-- <div class="m-np"> -->
|
||||
<!-- <NowPlaying class="hidden"/> -->
|
||||
<!-- </div> -->
|
||||
<div class="s">
|
||||
<Search
|
||||
v-model:search="search"
|
||||
@expandSearch="expandSearch"
|
||||
@collapseSearch="collapseSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="q">
|
||||
<UpNext v-model:up_next="up_next" @expandQueue="expandQueue" />
|
||||
</div>
|
||||
<div class="r">
|
||||
<RecommendedArtist />
|
||||
<div class="grid">
|
||||
<div class="r-content border rounded">
|
||||
<div class="r-dash" v-if="current_tab == tabs.home">
|
||||
<DashBoard/>
|
||||
</div>
|
||||
<div class="r-search" v-if="current_tab == tabs.search">
|
||||
<Search
|
||||
v-model:search="search"
|
||||
@expandSearch="expandSearch"
|
||||
@collapseSearch="collapseSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="r-queue" v-if="current_tab == tabs.queue">
|
||||
<UpNext v-model:up_next="up_next" @expandQueue="expandQueue" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-keys card-dark border">
|
||||
<Tabs :current_tab="current_tab" :tabs="tabs" @changeTab="changeTab" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -22,8 +27,11 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import Search from "../Search.vue";
|
||||
import UpNext from "./UpNext.vue";
|
||||
import RecommendedArtist from "@/components/RightSideBar/Recommendation.vue";
|
||||
import UpNext from "./Queue.vue";
|
||||
import Tabs from "./Tabs.vue";
|
||||
import Main from "./Home/Main.vue";
|
||||
|
||||
const DashBoard = Main;
|
||||
|
||||
let up_next = ref(true);
|
||||
let search = ref(false);
|
||||
@@ -39,17 +47,54 @@ const expandSearch = () => {
|
||||
const collapseSearch = () => {
|
||||
search.value = false;
|
||||
};
|
||||
|
||||
const tabs = {
|
||||
home: "home",
|
||||
search: "search",
|
||||
queue: "queue",
|
||||
};
|
||||
|
||||
const current_tab = ref(tabs.search);
|
||||
|
||||
function changeTab(tab) {
|
||||
current_tab.value = tab;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.r-sidebar {
|
||||
border-radius: 5px;
|
||||
margin-right: 0.5rem;
|
||||
margin-bottom: $small;
|
||||
overflow-y: auto;
|
||||
width: 30em;
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
grid-template-rows: min-content min-content auto;
|
||||
width: 34em;
|
||||
|
||||
.grid {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-areas: "content tabs";
|
||||
|
||||
.r-content {
|
||||
grid-area: content;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
margin: $small $small $small 0;
|
||||
|
||||
.r-search {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.r-dash {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.r-queue {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-keys {
|
||||
grid-area: tabs;
|
||||
width: 3rem;
|
||||
padding: $small;
|
||||
margin-left: $small;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<div class="up-next border">
|
||||
<p class="heading">COMING UP NEXT</p>
|
||||
<div class="r-grid">
|
||||
<div class="main-item h-1 border" @click="playNext">
|
||||
<div
|
||||
class="album-art image"
|
||||
:style="{
|
||||
backgroundImage: `url("${next.image}")`,
|
||||
}"
|
||||
></div>
|
||||
<div class="tags">
|
||||
<p class="title ellip">{{ next.title }}</p>
|
||||
<hr />
|
||||
<p class="artist ellip">
|
||||
<span v-for="artist in putCommas(next.artists)" :key="artist">{{
|
||||
artist
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scrollable-r border">
|
||||
<TrackItem v-for="song in queue" :key="song" :track="song" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, toRefs } from "@vue/reactivity";
|
||||
import perks from "@/composables/perks.js";
|
||||
import audio from "@/composables/playAudio.js";
|
||||
import { watch } from "@vue/runtime-core";
|
||||
import TrackItem from "../shared/TrackItem.vue";
|
||||
|
||||
export default {
|
||||
props: ["up_next"],
|
||||
setup(props, { emit }) {
|
||||
const is_expanded = toRefs(props).up_next;
|
||||
const queue = ref(perks.queue);
|
||||
const next = ref(perks.next);
|
||||
|
||||
let collapse = () => {
|
||||
emit("expandQueue");
|
||||
};
|
||||
|
||||
watch(is_expanded, (newVal) => {
|
||||
if (newVal) {
|
||||
setTimeout(() => {
|
||||
perks.focusCurrent();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
const { playNext } = audio;
|
||||
|
||||
const putCommas = perks.putCommas;
|
||||
return {
|
||||
collapse,
|
||||
is_expanded,
|
||||
playNext,
|
||||
putCommas,
|
||||
queue,
|
||||
next,
|
||||
};
|
||||
},
|
||||
components: { TrackItem },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.up-next {
|
||||
background-color: $card-dark;
|
||||
border-radius: 0.5rem;
|
||||
padding: $small;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
|
||||
|
||||
|
||||
.heading {
|
||||
position: relative;
|
||||
margin: 0.5rem 0 1rem 0;
|
||||
}
|
||||
|
||||
.main-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
.album-art {
|
||||
width: 4.5rem;
|
||||
height: 4.5rem;
|
||||
background-image: url(../../assets/images/null.webp);
|
||||
margin: 0 0.5rem 0 0;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.tags {
|
||||
hr {
|
||||
border: none;
|
||||
margin: 0.3rem;
|
||||
}
|
||||
.title {
|
||||
width: 20rem;
|
||||
margin: 0;
|
||||
}
|
||||
.artist {
|
||||
width: 20rem;
|
||||
margin: 0;
|
||||
font-size: small;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
.r-grid {
|
||||
position: relative;
|
||||
height: calc(100% - 2rem);
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: min-content 1fr;
|
||||
|
||||
.scrollable-r {
|
||||
margin-bottom: $small;
|
||||
padding: $small;
|
||||
overflow: auto;
|
||||
background-color: $card-dark;
|
||||
border-radius: 0.5rem;
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="r-tabs">
|
||||
<button v-for="tab in props.tabs"
|
||||
@click="changeTab(tab)"
|
||||
:key="tab"
|
||||
class="image t-item rounded"
|
||||
:class="{ active_tab: props.current_tab == tab }, `${tab}`"
|
||||
></button>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>import { onMounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
current_tab: String,
|
||||
tabs: Object,
|
||||
});
|
||||
|
||||
const emit = defineEmits(['changeTab'])
|
||||
|
||||
function changeTab(tab) {
|
||||
if (tab == props.current_tab) return;
|
||||
|
||||
emit('changeTab', tab)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.r-tabs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $small;
|
||||
|
||||
.t-item {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-size: 1.5rem;
|
||||
}
|
||||
|
||||
.active_tab {
|
||||
border-right: solid;
|
||||
border-radius: $small 0 0 $small;
|
||||
}
|
||||
|
||||
.search {
|
||||
background-image: url("../../assets/icons/search.svg");
|
||||
background-color: rgba(35, 35, 66, 0.247);
|
||||
}
|
||||
|
||||
.queue {
|
||||
background-image: url("../../assets/icons/queue.svg");
|
||||
background-color: rgba(46, 25, 33, 0.445);
|
||||
}
|
||||
|
||||
.home {
|
||||
background-image: url("../../assets/icons/dashboard.svg");
|
||||
background-color: rgba(148, 102, 50, 0.445);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,169 +0,0 @@
|
||||
<template>
|
||||
<div class="up-next border">
|
||||
<p class="heading">
|
||||
COMING UP NEXT <span class="more" @click="collapse">SEE ALL</span>
|
||||
</p>
|
||||
<div class="main-item h-1 border" @click="playNext">
|
||||
<div
|
||||
class="album-art image"
|
||||
:style="{
|
||||
backgroundImage: `url("${next.image}")`,
|
||||
}"
|
||||
></div>
|
||||
<div class="tags">
|
||||
<p class="title ellip">{{ next.title }}</p>
|
||||
<hr />
|
||||
<p class="artist ellip">
|
||||
<span v-for="artist in putCommas(next.artists)" :key="artist">{{
|
||||
artist
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
:class="{ v0: !is_expanded, v1: is_expanded }"
|
||||
class="scrollable border"
|
||||
>
|
||||
<TrackItem v-for="song in queue" :key="song" :track="song" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, toRefs } from "@vue/reactivity";
|
||||
import perks from "@/composables/perks.js";
|
||||
import audio from "@/composables/playAudio.js";
|
||||
import { watch } from "@vue/runtime-core";
|
||||
import TrackItem from "../shared/TrackItem.vue";
|
||||
|
||||
export default {
|
||||
props: ["up_next"],
|
||||
setup(props, { emit }) {
|
||||
const is_expanded = toRefs(props).up_next;
|
||||
const queue = ref(perks.queue);
|
||||
const next = ref(perks.next);
|
||||
|
||||
let collapse = () => {
|
||||
emit("expandQueue");
|
||||
};
|
||||
|
||||
watch(is_expanded, (newVal) => {
|
||||
if (newVal) {
|
||||
setTimeout(() => {
|
||||
perks.focusCurrent();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
const { playNext } = audio;
|
||||
|
||||
const putCommas = perks.putCommas;
|
||||
return {
|
||||
collapse,
|
||||
is_expanded,
|
||||
playNext,
|
||||
putCommas,
|
||||
queue,
|
||||
next,
|
||||
};
|
||||
},
|
||||
components: { TrackItem },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.up-next .v0 {
|
||||
max-height: 0;
|
||||
transition: max-height 0.5s ease;
|
||||
visibility: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.up-next .v1 {
|
||||
max-height: 21em;
|
||||
transition: max-height 0.5s ease;
|
||||
padding: $small;
|
||||
|
||||
.currentInQueue {
|
||||
border: 2px solid $pink;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.up-next {
|
||||
padding: 0.5rem;
|
||||
margin-top: $small;
|
||||
background-color: $card-dark;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.up-next .heading {
|
||||
position: relative;
|
||||
margin: 0.5rem 0 1rem 0;
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
right: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background: $blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.up-next .main-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
.album-art {
|
||||
width: 4.5rem;
|
||||
height: 4.5rem;
|
||||
background-image: url(../../assets/images/null.webp);
|
||||
margin: 0 0.5rem 0 0;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.tags {
|
||||
hr {
|
||||
border: none;
|
||||
margin: 0.3rem;
|
||||
}
|
||||
.title {
|
||||
width: 20rem;
|
||||
margin: 0;
|
||||
}
|
||||
.artist {
|
||||
width: 20rem;
|
||||
margin: 0;
|
||||
font-size: small;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
.up-next .scrollable {
|
||||
overflow-y: auto;
|
||||
background-color: $card-dark;
|
||||
border-radius: 0.5rem;
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+29
-27
@@ -1,33 +1,35 @@
|
||||
<template>
|
||||
<div class="right-search border" ref="searchComponent">
|
||||
<div class="input">
|
||||
<Loader />
|
||||
<Filters :filters="filters" @removeFilter="removeFilter" />
|
||||
<div class="input-loader border">
|
||||
<input
|
||||
type="search"
|
||||
id="search"
|
||||
@focus="activateMagicFlag"
|
||||
@blur="removeMagicFlag"
|
||||
@keyup.backspace="removeLastFilter"
|
||||
placeholder="find your music"
|
||||
v-model="query"
|
||||
/>
|
||||
<div class="search-icon image"></div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<div
|
||||
class="suggestions v00"
|
||||
:class="{
|
||||
v00: !filters.length && !query,
|
||||
v11: filters.length || query,
|
||||
}"
|
||||
>
|
||||
<div class="item">Kenny Rogers</div>
|
||||
<div class="right-search" ref="searchComponent">
|
||||
<div>
|
||||
<div class="input">
|
||||
<Loader />
|
||||
<Filters :filters="filters" @removeFilter="removeFilter" />
|
||||
<div class="input-loader border">
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
@focus="activateMagicFlag"
|
||||
@blur="removeMagicFlag"
|
||||
@keyup.backspace="removeLastFilter"
|
||||
placeholder="find your music"
|
||||
v-model="query"
|
||||
/>
|
||||
<div class="search-icon image"></div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<div
|
||||
class="suggestions v00"
|
||||
:class="{
|
||||
v00: !filters.length && !query,
|
||||
v11: filters.length || query,
|
||||
}"
|
||||
>
|
||||
<div class="item">Kenny Rogers</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="separator no-border"></div>
|
||||
<Options :magic_flag="magic_flag" @addFilter="addFilter" />
|
||||
</div>
|
||||
<div class="separator no-border"></div>
|
||||
<Options :magic_flag="magic_flag" @addFilter="addFilter" />
|
||||
<div class="scrollable" :class="{ v0: !is_hidden, v1: is_hidden }">
|
||||
<TracksGrid
|
||||
:tracks="tracks.tracks"
|
||||
|
||||
@@ -35,7 +35,6 @@ export default {
|
||||
border-radius: 0.5rem;
|
||||
background: #0f131b44;
|
||||
|
||||
margin-left: $small;
|
||||
margin-top: $small;
|
||||
padding: $small 0;
|
||||
overflow-x: hidden;
|
||||
|
||||
@@ -38,8 +38,8 @@ export default {
|
||||
.right-search .artists-results {
|
||||
border-radius: 0.5rem;
|
||||
background: #1214178c;
|
||||
margin: 0 0 0 $small;
|
||||
padding: $small 0;
|
||||
margin-bottom: $small;
|
||||
|
||||
.grid {
|
||||
padding: 0 0 0 $small;
|
||||
|
||||
@@ -29,9 +29,10 @@ export default {
|
||||
<style lang="scss">
|
||||
.right-search .filter {
|
||||
display: flex;
|
||||
margin-left: 3rem;
|
||||
margin-left: 2rem;
|
||||
height: 2rem;
|
||||
|
||||
|
||||
.item {
|
||||
&:hover {
|
||||
width: 4rem;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="morexx">
|
||||
<button @click="loadMore">
|
||||
<div class="text">Load All</div>
|
||||
<div class="text">Load More</div>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="loaderx" :class="{ loader: loading, not_loader: !loading }">
|
||||
<div class="content" v-if="!loading">/</div>
|
||||
<div v-if="!loading">😹</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -18,15 +18,14 @@ export default {
|
||||
<style lang="scss">
|
||||
.loaderx {
|
||||
position: absolute;
|
||||
left: 0.65rem;
|
||||
top: 0.65rem;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.loader {
|
||||
border: dotted $blue;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.25s linear infinite;
|
||||
|
||||
@keyframes spin {
|
||||
@@ -40,8 +39,7 @@ export default {
|
||||
}
|
||||
|
||||
.not_loader {
|
||||
border: solid 1px;
|
||||
border-radius: 50%;
|
||||
background-image: url("");
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="options" v-if="magic_flag">
|
||||
<div class="options border rounded">
|
||||
<div class="item info">Filter by:</div>
|
||||
<div
|
||||
class="item"
|
||||
@@ -54,6 +54,7 @@ export default {
|
||||
<style lang="scss">
|
||||
.right-search .options {
|
||||
display: flex;
|
||||
margin-bottom: $small;
|
||||
|
||||
.item {
|
||||
margin: $small;
|
||||
|
||||
@@ -41,7 +41,6 @@ function loadMore() {
|
||||
<style lang="scss">
|
||||
.right-search .tracks-results {
|
||||
border-radius: 0.5rem;
|
||||
margin-left: $small;
|
||||
padding: $small;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -51,6 +51,10 @@ const playThis = (song) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.currentInQueue {
|
||||
border: solid 2px $pink;
|
||||
}
|
||||
|
||||
.track-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user