mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 12:33:03 +00:00
rewrite search tabbing
This commit is contained in:
@@ -38,9 +38,11 @@ import LoadMore from "./LoadMore.vue";
|
||||
|
||||
const search = useSearchStore();
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
album_grid?: boolean;
|
||||
}>();
|
||||
|
||||
console.log(search.albums);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -1,28 +1,36 @@
|
||||
<template>
|
||||
<div class="right-search">
|
||||
<TabsWrapper>
|
||||
<Tab name="tracks">
|
||||
<TracksGrid :isOnSearchPage="isOnSearchPage" />
|
||||
</Tab>
|
||||
<Tab name="albums">
|
||||
<ArtistGrid :album_grid="true" />
|
||||
</Tab>
|
||||
<Tab name="artists">
|
||||
<ArtistGrid />
|
||||
</Tab>
|
||||
<TabsWrapper
|
||||
:isOnSearchPage="isOnSearchPage"
|
||||
:tabs="tabs"
|
||||
@switchTab="switchTab"
|
||||
:currentTab="currentTab"
|
||||
>
|
||||
<Tab :name="currentTab" :isOnSearchPage="isOnSearchPage" />
|
||||
</TabsWrapper>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ArtistGrid from "./ArtistGrid.vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
import Tab from "./Tab.vue";
|
||||
import TabsWrapper from "./TabsWrapper.vue";
|
||||
import TracksGrid from "./TracksGrid.vue";
|
||||
import useSearchStore from "@/stores/search";
|
||||
|
||||
const props = defineProps<{
|
||||
const search = useSearchStore();
|
||||
defineProps<{
|
||||
isOnSearchPage?: boolean;
|
||||
}>();
|
||||
|
||||
const tabs = ["tracks", "albums", "artists"];
|
||||
|
||||
const currentTab = ref("tracks");
|
||||
|
||||
function switchTab(tab: string) {
|
||||
currentTab.value = tab;
|
||||
search.switchTab(tab);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -1,13 +1,39 @@
|
||||
<template>
|
||||
<div v-show="name == s.currentTab">
|
||||
<slot />
|
||||
</div>
|
||||
<component :is="getComponent()?.component" v-bind="getComponent()?.props" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useSearchStore from "@/stores/search";
|
||||
const s = useSearchStore();
|
||||
defineProps<{
|
||||
import ArtistGrid from "./ArtistGrid.vue";
|
||||
import TracksGrid from "./TracksGrid.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
name: string;
|
||||
isOnSearchPage?: boolean;
|
||||
}>();
|
||||
|
||||
function getComponent() {
|
||||
switch (props.name) {
|
||||
case "tracks":
|
||||
return {
|
||||
component: TracksGrid,
|
||||
props: {
|
||||
isOnSearchPage: props.isOnSearchPage,
|
||||
},
|
||||
};
|
||||
case "albums":
|
||||
return {
|
||||
component: ArtistGrid,
|
||||
props: {
|
||||
album_grid: true,
|
||||
},
|
||||
};
|
||||
case "artists":
|
||||
return {
|
||||
component: ArtistGrid,
|
||||
props: {},
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
<template>
|
||||
<div id="right-tabs" class="rounded">
|
||||
<div class="tab-buttons-wrapper">
|
||||
<div id="tabheaders" class="rounded-sm noscroll">
|
||||
<div
|
||||
class="tab"
|
||||
v-for="slot in $slots.default()"
|
||||
:key="slot.key"
|
||||
@click="s.changeTab(slot.props.name)"
|
||||
:class="{ activetab: slot.props.name === s.currentTab }"
|
||||
>
|
||||
{{ slot.props.name }}
|
||||
<Teleport :disabled="!isOnSearchPage" to="#nav-tab-headers">
|
||||
<div class="tabheaders rounded-sm noscroll">
|
||||
<div
|
||||
class="tab"
|
||||
v-for="tab in tabs"
|
||||
:key="tab"
|
||||
@click="switchTab(tab)"
|
||||
:class="{ activetab: tab === currentTab }"
|
||||
>
|
||||
{{ tab }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</div>
|
||||
|
||||
<div id="tab-content">
|
||||
@@ -21,9 +23,19 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useSearchStore from "@/stores/search";
|
||||
defineProps<{
|
||||
isOnSearchPage?: boolean;
|
||||
tabs: string[];
|
||||
currentTab: string;
|
||||
}>();
|
||||
|
||||
const s = useSearchStore();
|
||||
const emit = defineEmits<{
|
||||
(e: "switchTab", tab: string): void;
|
||||
}>();
|
||||
|
||||
function switchTab(tab: string) {
|
||||
emit("switchTab", tab);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -38,44 +50,9 @@ const s = useSearchStore();
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#tabheaders {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, max-content);
|
||||
justify-content: space-around;
|
||||
margin: 1rem;
|
||||
width: max-content;
|
||||
background: linear-gradient(37deg, $gray1, $gray2, $gray1);
|
||||
height: 2rem;
|
||||
|
||||
& > * {
|
||||
border-left: solid 1px $gray3;
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
padding: 0 $small;
|
||||
|
||||
&:first-child {
|
||||
border-left: solid 1px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.activetab {
|
||||
background-color: $darkblue;
|
||||
transition: all 0.3s ease;
|
||||
border-left: solid 1px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
#tab-content {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
overflow: scroll;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
<template>
|
||||
<div id="tracks-results">
|
||||
<div id="tracks-results" class="noscroll">
|
||||
<div v-if="search.tracks.value.length">
|
||||
<div>
|
||||
<TrackComponent
|
||||
v-for="(track, index) in search.tracks.value"
|
||||
:key="track.trackid"
|
||||
:isCurrent="queue.currentid == track.trackid"
|
||||
:isHighlighted="false"
|
||||
:isPlaying="queue.playing"
|
||||
:track="track"
|
||||
@PlayThis="updateQueue(index)"
|
||||
/>
|
||||
</div>
|
||||
<TrackComponent
|
||||
v-for="(track, index) in search.tracks.value"
|
||||
:key="track.trackid"
|
||||
:isCurrent="queue.currentid == track.trackid"
|
||||
:isHighlighted="false"
|
||||
:isPlaying="queue.playing"
|
||||
:track="track"
|
||||
@PlayThis="updateQueue(index)"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="t-center"><h5>🤷</h5></div>
|
||||
<LoadMore v-if="search.tracks.more" :loader="search.loadTracks" />
|
||||
@@ -52,10 +50,3 @@ if (props.isOnSearchPage) {
|
||||
use_song_item = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.right-search #tracks-results {
|
||||
height: 100% !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="nav-search-input">
|
||||
<SearchInput />
|
||||
<div id="nav-tab-headers"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -10,6 +11,12 @@ import SearchInput from "@/components/RightSideBar/SearchInput.vue";
|
||||
|
||||
<style lang="scss">
|
||||
.nav-search-input {
|
||||
display: flex;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 2rem;
|
||||
|
||||
#gsearch-input {
|
||||
display: unset;
|
||||
|
||||
@@ -22,5 +29,9 @@ import SearchInput from "@/components/RightSideBar/SearchInput.vue";
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.tabheaders {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="xartist" :class="{ _is_on_sidebar: alt }">
|
||||
<div class="artist-card" :class="{ _is_on_sidebar: alt }">
|
||||
<img
|
||||
class="artist-image shadow-sm"
|
||||
:src="imguri + artist.image"
|
||||
@@ -24,7 +24,7 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.xartist {
|
||||
.artist-card {
|
||||
flex: 0 0 auto;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
@@ -41,11 +41,5 @@ defineProps<{
|
||||
transition: all 0.5s ease-in-out;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
// &:hover {
|
||||
// .artist-image {
|
||||
// border-radius: 10%;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user