rewrite search tabbing

This commit is contained in:
geoffrey45
2022-09-04 15:30:23 +03:00
parent 24bfa73ab6
commit b7c158a785
12 changed files with 172 additions and 108 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
@import "./app-grid.scss", "./controls.scss", "./inputs.scss",
"./scrollbars.scss", "./state.scss", "./variants.scss", "./basic.scss";
"./scrollbars.scss", "./state.scss", "./variants.scss", "./basic.scss",
"./search-tabheaders.scss";
:root {
--separator: #ffffff46;
@@ -0,0 +1,34 @@
.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;
}
}
@@ -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">
+21 -13
View File
@@ -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">
+32 -6
View File
@@ -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>
+11
View File
@@ -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>
+2 -8
View File
@@ -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>
+11 -7
View File
@@ -1,18 +1,19 @@
import { Directive } from "vue";
import { createPopper } from "@popperjs/core";
let tooltip: HTMLElement;
export default {
mounted(el, binding) {
let isHovered = false;
const tooltip = document.getElementById("tooltip") as HTMLElement;
el.addEventListener("mouseenter", () => {
el.addEventListener("mouseover", () => {
isHovered = true;
setTimeout(() => {
tooltip.innerText = binding.value;
if (isHovered) {
tooltip.innerText = binding.value;
tooltip.style.display = "unset";
createPopper(el, tooltip, {
@@ -27,16 +28,19 @@ export default {
],
});
}
}, 1000);
}, 1500);
});
el.addEventListener("mouseleave", () => {
el.addEventListener("mouseout", () => {
isHovered = false;
tooltip.style.display = "none";
});
},
beforeUnmount(el: HTMLElement) {
el.removeEventListener("mouseenter", () => {});
el.removeEventListener("mouseleave", () => {});
const tooltip = document.getElementById("tooltip") as HTMLElement;
tooltip.style.display = "none";
el.removeEventListener("mouseover", () => {});
el.removeEventListener("mouseout", () => {});
},
} as Directive;
+6 -3
View File
@@ -1,3 +1,4 @@
import { Routes } from "./../composables/enums";
import { ref, reactive } from "@vue/reactivity";
import { defineStore } from "pinia";
import { AlbumInfo, Artist, Playlist, Track } from "../interfaces";
@@ -13,6 +14,7 @@ import { watch } from "vue";
import useDebouncedRef from "../utils/useDebouncedRef";
import useTabStore from "./tabs";
import useLoaderStore from "./loader";
import { useRoute } from "vue-router";
/**
*
* Scrolls on clicking the loadmore button
@@ -31,6 +33,7 @@ export default defineStore("search", () => {
// @ts-ignore
const query = useDebouncedRef(null, 600);
const { startLoading, stopLoading } = useLoaderStore();
const route = useRoute();
const currentTab = ref("tracks");
const RESULT_COUNT = 6;
@@ -154,7 +157,7 @@ export default defineStore("search", () => {
const tabs = useTabStore();
if (tabs.current !== "search") {
if (route.name !== Routes.search && tabs.current !== "search") {
tabs.switchToSearch();
}
@@ -202,7 +205,7 @@ export default defineStore("search", () => {
}
);
function changeTab(tab: string) {
function switchTab(tab: string) {
currentTab.value = tab;
}
@@ -217,6 +220,6 @@ export default defineStore("search", () => {
loadTracks,
loadAlbums,
loadArtists,
changeTab,
switchTab,
};
});
+15 -2
View File
@@ -13,7 +13,6 @@ import Main from "@/components/RightSideBar/Search/Main.vue";
<style lang="scss">
.search-view {
height: 100%;
// background-color: $black;
padding-top: 0;
margin-right: -1rem;
@@ -22,8 +21,22 @@ import Main from "@/components/RightSideBar/Search/Main.vue";
overflow: auto;
}
.artists-results {
margin-right: $small;
margin-left: -$small;
}
.search-results-grid {
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
.artist-card {
padding: 0 1rem;
}
}
#tracks-results {
margin-right: 1rem;
margin-left: -2.25rem;
}
}
</style>