mirror of
https://github.com/tcsenpai/swingmusic.git
synced 2025-07-29 14:12:21 +00:00
rebuild search route with custom pages for tracks, album, and artists
This commit is contained in:
parent
264406aef4
commit
8e258eaf24
@ -86,17 +86,17 @@ button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.btn-active {
|
.btn-active {
|
||||||
background-image: linear-gradient($darkestblue, $darkblue);
|
background-image: linear-gradient($darkestblue, $darkblue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-more {
|
.btn-more {
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
|
|
||||||
svg {
|
|
||||||
transform: scale(1.25);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
|
@ -6,11 +6,13 @@
|
|||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// applies to playlist list page
|
||||||
.content-page {
|
.content-page {
|
||||||
margin-right: calc(0rem - ($medium + 4px));
|
margin-right: calc(0rem - ($medium + 4px));
|
||||||
padding-right: calc(1rem - 3px) !important;
|
padding-right: calc(1rem - 3px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// virtual scroller pages: folder, playlist, album
|
||||||
.header-list-layout {
|
.header-list-layout {
|
||||||
margin-right: calc(0rem - ($medium + 4px)) !important;
|
margin-right: calc(0rem - ($medium + 4px)) !important;
|
||||||
|
|
||||||
@ -22,4 +24,8 @@
|
|||||||
#app-grid.noSidebar > #acontent {
|
#app-grid.noSidebar > #acontent {
|
||||||
padding-right: 1rem !important;
|
padding-right: 1rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-view {
|
||||||
|
margin-right: -1rem !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ const menus = [
|
|||||||
{
|
{
|
||||||
name: "search",
|
name: "search",
|
||||||
route_name: Routes.search,
|
route_name: Routes.search,
|
||||||
params: { page: "top" },
|
params: { page: "tracks" },
|
||||||
icon: SearchSvg,
|
icon: SearchSvg,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="artists-results" v-auto-animate>
|
<div class="artists-results" v-auto-animate>
|
||||||
<div
|
<div
|
||||||
v-auto-animate
|
|
||||||
class="search-results-grid"
|
class="search-results-grid"
|
||||||
v-if="album_grid == true && search.albums.value.length"
|
v-if="album_grid == true && search.albums.value.length"
|
||||||
>
|
>
|
||||||
<AlbumCard v-for="a in search.albums.value" :key="a.albumid" :album="a" />
|
<AlbumCard v-for="a in search.albums.value" :key="a.albumid" :album="a" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-auto-animate
|
|
||||||
class="search-results-grid"
|
class="search-results-grid"
|
||||||
v-else-if="!album_grid && search.artists.value.length"
|
v-else-if="!album_grid && search.artists.value.length"
|
||||||
>
|
>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="tracks-results" class="noscroll">
|
<div id="tracks-results" class="noscroll">
|
||||||
<div v-if="search.tracks.value.length" v-auto-animate>
|
<div v-if="search.tracks.value.length">
|
||||||
<TrackComponent
|
<TrackComponent
|
||||||
v-for="(track, index) in search.tracks.value"
|
v-for="(track, index) in search.tracks.value"
|
||||||
:key="track.trackid"
|
:key="track.trackid"
|
||||||
@ -18,7 +18,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from "vue";
|
import { computed, onMounted } from "vue";
|
||||||
|
|
||||||
import SongItem from "@/components/shared/SongItem.vue";
|
import SongItem from "@/components/shared/SongItem.vue";
|
||||||
import TrackItem from "@/components/shared/TrackItem.vue";
|
import TrackItem from "@/components/shared/TrackItem.vue";
|
||||||
@ -51,4 +51,8 @@ let use_song_item: boolean = false;
|
|||||||
if (props.isOnSearchPage) {
|
if (props.isOnSearchPage) {
|
||||||
use_song_item = true;
|
use_song_item = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
search.switchTab("tracks");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
import SearchInput from "@/components/shared/NavSearchInput.vue";
|
import SearchInput from "@/components/shared/NavSearchInput.vue";
|
||||||
import { Routes } from "@/composables/enums";
|
import { Routes } from "@/composables/enums";
|
||||||
import { subPath } from "@/interfaces";
|
import { subPath } from "@/interfaces";
|
||||||
import { focusElem } from "@/utils";
|
import { focusElemByClass } from "@/utils";
|
||||||
import { onUpdated } from "vue";
|
import { onUpdated } from "vue";
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@ -44,7 +44,7 @@ defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
onUpdated(() => {
|
onUpdated(() => {
|
||||||
focusElem("inthisfolder");
|
focusElemByClass("inthisfolder");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ defineProps<{
|
|||||||
gap: $small;
|
gap: $small;
|
||||||
padding: $medium;
|
padding: $medium;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
|
height: fit-content;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $gray4;
|
background-color: $gray4;
|
||||||
|
@ -32,6 +32,7 @@ defineProps<{
|
|||||||
padding: 1.2rem 1rem !important;
|
padding: 1.2rem 1rem !important;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
font-weight: bolder;
|
font-weight: bolder;
|
||||||
|
height: fit-content;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $gray4;
|
background-color: $gray4;
|
||||||
|
@ -49,11 +49,12 @@ async function loadMoreTracks(index: number) {
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadMoreAlbums(index: number) {
|
async function loadMoreAlbums(index: number, count: number) {
|
||||||
const response = await axios.get(loadMoreUrl, {
|
const response = await axios.get(loadMoreUrl, {
|
||||||
params: {
|
params: {
|
||||||
type: "albums",
|
type: "albums",
|
||||||
index: index,
|
index: index,
|
||||||
|
count: count,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// "local" | "remote"
|
// "local" | "remote"
|
||||||
let mode = "local";
|
let mode = "remote";
|
||||||
|
|
||||||
export interface D<T = string> {
|
export interface D<T = string> {
|
||||||
[key: string]: T;
|
[key: string]: T;
|
||||||
@ -7,7 +7,7 @@ export interface D<T = string> {
|
|||||||
|
|
||||||
const domains: D = {
|
const domains: D = {
|
||||||
local: "http://localhost:",
|
local: "http://localhost:",
|
||||||
remote: "http://10.5.71.115:",
|
remote: "http://10.16.22.240:",
|
||||||
};
|
};
|
||||||
|
|
||||||
const ports = {
|
const ports = {
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
updateQueue(t.data.index !== undefined ? t.data.index : t.index)
|
updateQueue(t.data.index !== undefined ? t.data.index : t.index)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<div class="bottom-padding" style="height: 64px"></div>
|
<div class="page-bottom-padding" style="height: 64px"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,6 +22,8 @@ import { useDebounce } from "@vueuse/core";
|
|||||||
function scrollOnLoad() {
|
function scrollOnLoad() {
|
||||||
const elem = document.getElementById("tab-content") as HTMLElement;
|
const elem = document.getElementById("tab-content") as HTMLElement;
|
||||||
|
|
||||||
|
if (elem === null) return;
|
||||||
|
|
||||||
elem.scroll({
|
elem.scroll({
|
||||||
top: elem.scrollHeight,
|
top: elem.scrollHeight,
|
||||||
left: 0,
|
left: 0,
|
||||||
@ -85,6 +87,7 @@ export default defineStore("search", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fetchAlbums(query: string) {
|
function fetchAlbums(query: string) {
|
||||||
|
console.log("fetching albums");
|
||||||
if (!query) return;
|
if (!query) return;
|
||||||
|
|
||||||
searchAlbums(query).then((res) => {
|
searchAlbums(query).then((res) => {
|
||||||
@ -92,6 +95,8 @@ export default defineStore("search", () => {
|
|||||||
albums.more = res.more;
|
albums.more = res.more;
|
||||||
albums.query = query;
|
albums.query = query;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("fetched albums");
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchArtists(query: string) {
|
function fetchArtists(query: string) {
|
||||||
@ -117,11 +122,11 @@ export default defineStore("search", () => {
|
|||||||
.then(() => scrollOnLoad());
|
.then(() => scrollOnLoad());
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadAlbums() {
|
function loadAlbums(count = 6) {
|
||||||
loadCounter.albums += RESULT_COUNT;
|
loadCounter.albums += count;
|
||||||
|
|
||||||
startLoading();
|
startLoading();
|
||||||
loadMoreAlbums(loadCounter.albums)
|
loadMoreAlbums(loadCounter.albums, count)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
albums.value = [...albums.value, ...res.albums];
|
albums.value = [...albums.value, ...res.albums];
|
||||||
albums.more = res.more;
|
albums.more = res.more;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import { focusElemByClass } from "@/utils";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { focusElem } from "@/utils";
|
|
||||||
|
|
||||||
const tablist = {
|
const tablist = {
|
||||||
home: "home",
|
home: "home",
|
||||||
@ -16,7 +16,7 @@ export default defineStore("tabs", {
|
|||||||
changeTab(tab: string) {
|
changeTab(tab: string) {
|
||||||
if (tab === this.tabs.queue) {
|
if (tab === this.tabs.queue) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
focusElem("currentInQueue");
|
focusElemByClass("currentInQueue");
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
this.current = tab;
|
this.current = tab;
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
import focusElem from "./useFocusElem";
|
import createSubPaths from "./useCreateSubPaths";
|
||||||
|
import focusElemByClass from "./useFocusElem";
|
||||||
|
import formatSeconds from "./useFormatSeconds";
|
||||||
|
import useFuse from "./useFuse";
|
||||||
|
import { readLocalStorage, writeLocalStorage } from "./useLocalStorage";
|
||||||
import putCommas from "./usePutCommas";
|
import putCommas from "./usePutCommas";
|
||||||
import useVisibility from "./useVisibility";
|
import useVisibility from "./useVisibility";
|
||||||
import formatSeconds from "./useFormatSeconds";
|
|
||||||
import createSubPaths from "./useCreateSubPaths";
|
|
||||||
import { readLocalStorage, writeLocalStorage } from "./useLocalStorage";
|
|
||||||
import useFuse from "./useFuse";
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
readLocalStorage,
|
readLocalStorage,
|
||||||
writeLocalStorage,
|
writeLocalStorage,
|
||||||
createSubPaths,
|
createSubPaths,
|
||||||
focusElem,
|
focusElemByClass,
|
||||||
useVisibility,
|
useVisibility,
|
||||||
formatSeconds,
|
formatSeconds,
|
||||||
putCommas,
|
putCommas,
|
||||||
useFuse,
|
useFuse,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
6
src/utils/useCalculateSearchItemCount.ts
Normal file
6
src/utils/useCalculateSearchItemCount.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const itemWidth = 160;
|
||||||
|
const itemMarginBottom = 24;
|
||||||
|
|
||||||
|
export default (containerWidth = 0, containerHeight = 0) => {
|
||||||
|
return Math.floor(containerWidth / itemWidth);
|
||||||
|
};
|
@ -4,7 +4,7 @@
|
|||||||
* @param delay Delay in milliseconds
|
* @param delay Delay in milliseconds
|
||||||
* @param pos Positioning of the focus element
|
* @param pos Positioning of the focus element
|
||||||
*/
|
*/
|
||||||
export default function focusElem(
|
export default function focusElemByClass(
|
||||||
className: string,
|
className: string,
|
||||||
delay?: number,
|
delay?: number,
|
||||||
pos?: any
|
pos?: any
|
||||||
|
@ -1,11 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="search-albums-view"></div>
|
<div class="search-albums-view grid-page" v-auto-animate>
|
||||||
|
<AlbumCard
|
||||||
|
v-for="album in search.albums.value"
|
||||||
|
:key="album.hash"
|
||||||
|
:album="album"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import AlbumCard from "@/components/shared/AlbumCard.vue";
|
||||||
|
import useSearchStore from "@/stores/search";
|
||||||
|
|
||||||
|
const search = useSearchStore();
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.search-albums-view {
|
// .search-albums-view.grid-page {
|
||||||
height: 100%;
|
// max-height: 100%;
|
||||||
}
|
// display: grid;
|
||||||
|
// grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
|
||||||
|
// gap: 1.75rem 0;
|
||||||
|
|
||||||
|
// padding-bottom: 4rem;
|
||||||
|
// padding-right: $medium;
|
||||||
|
|
||||||
|
// overflow: auto;
|
||||||
|
// }
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="search-artists-view"></div>
|
<div v-auto-animate class="search-artists-view grid-page">
|
||||||
|
<ArtistCard
|
||||||
|
v-for="artist in search.artists.value"
|
||||||
|
:key="artist.image"
|
||||||
|
:artist="artist"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import ArtistCard from "@/components/shared/ArtistCard.vue";
|
||||||
|
import useSearchStore from "@/stores/search";
|
||||||
|
|
||||||
|
const search = useSearchStore();
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.search-artists-view {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,20 +1,48 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="search-view">
|
<div class="search-view">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<button v-for="page in pages">{{ page }}</button>
|
<button
|
||||||
|
v-for="page in pages"
|
||||||
|
:class="{ 'btn-active': page === $route.params.page }"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
$router.push({ name: Routes.search, params: { page: page } });
|
||||||
|
search.switchTab(page);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ page }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="noscroll">
|
<div ref="page" class="page noscroll" v-auto-animate>
|
||||||
<component :is="getComponent()" />
|
<component :is="component" />
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
class="load-more"
|
||||||
|
:class="{ 'btn-disabled': !canLoadMore }"
|
||||||
|
@click="loadMore"
|
||||||
|
>
|
||||||
|
Load more
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
import { computed, onMounted, ref } from "vue";
|
||||||
import TracksPage from "./tracks.vue";
|
import TracksPage from "./tracks.vue";
|
||||||
import AlbumPage from "./albums.vue";
|
import AlbumPage from "./albums.vue";
|
||||||
import ArtistPage from "./artists.vue";
|
import ArtistPage from "./artists.vue";
|
||||||
|
import { Routes } from "@/composables/enums";
|
||||||
|
import useSearchStore from "@/stores/search";
|
||||||
|
import { focusElemByClass } from "@/utils";
|
||||||
|
|
||||||
|
// width of album and artist cards
|
||||||
|
const defaultItemCount = 6;
|
||||||
|
const gridItemWidth = 160;
|
||||||
|
const page = ref<HTMLElement>();
|
||||||
|
|
||||||
|
const search = useSearchStore();
|
||||||
|
|
||||||
enum pages {
|
enum pages {
|
||||||
tracks = "tracks",
|
tracks = "tracks",
|
||||||
@ -23,10 +51,9 @@ enum pages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const page = route.params.page as string;
|
|
||||||
|
|
||||||
function getComponent() {
|
const component = computed(() => {
|
||||||
switch (page) {
|
switch (route.params.page) {
|
||||||
case pages.tracks:
|
case pages.tracks:
|
||||||
return TracksPage;
|
return TracksPage;
|
||||||
case pages.albums:
|
case pages.albums:
|
||||||
@ -38,22 +65,101 @@ function getComponent() {
|
|||||||
default:
|
default:
|
||||||
return TracksPage;
|
return TracksPage;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function loadTracks() {
|
||||||
|
search.loadTracks();
|
||||||
|
focusElemByClass("page-bottom-padding", 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getGridRowItemCount() {
|
||||||
|
if (page.value?.offsetWidth === undefined) return defaultItemCount;
|
||||||
|
const page_width = page.value?.offsetWidth - 16;
|
||||||
|
return Math.floor(page_width / gridItemWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToGridPageBottom() {
|
||||||
|
const elem = document.getElementsByClassName("grid-page")[0] as HTMLElement;
|
||||||
|
setTimeout(() => {
|
||||||
|
elem.scrollTo(0, elem.scrollHeight);
|
||||||
|
}, 250);
|
||||||
|
|
||||||
|
// const elemWidth = elem.offsetWidth;
|
||||||
|
// console.log(Math.floor(elemWidth / 160));
|
||||||
|
// elem.scroll({
|
||||||
|
// top: elem.scrollHeight,
|
||||||
|
// behavior: "smooth",
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadAlbums() {
|
||||||
|
scrollToGridPageBottom();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// search.loadAlbums();
|
||||||
|
const itemCount = getGridRowItemCount();
|
||||||
|
search.loadAlbums(itemCount);
|
||||||
|
|
||||||
|
scrollToGridPageBottom();
|
||||||
|
}, 250);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadArtists() {
|
||||||
|
// const itemCount = getGridRowItemCount();
|
||||||
|
search.loadArtists();
|
||||||
|
|
||||||
|
scrollToGridPageBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMore() {
|
||||||
|
switch (route.params.page) {
|
||||||
|
case pages.tracks:
|
||||||
|
loadTracks();
|
||||||
|
break;
|
||||||
|
case pages.albums:
|
||||||
|
loadAlbums();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pages.artists:
|
||||||
|
loadArtists();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const canLoadMore = computed(() => {
|
||||||
|
switch (route.params.page) {
|
||||||
|
case pages.tracks:
|
||||||
|
return search.tracks.more;
|
||||||
|
case pages.albums:
|
||||||
|
return search.albums.more;
|
||||||
|
case pages.artists:
|
||||||
|
return search.artists.more;
|
||||||
|
default:
|
||||||
|
false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
search.switchTab(route.params.page as string);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.search-view {
|
.search-view {
|
||||||
height: calc(100% - 1rem);
|
height: calc(100% - 1rem);
|
||||||
width: calc(100% - $small);
|
|
||||||
display: grid;
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
grid-template-rows: max-content 1fr;
|
grid-template-rows: max-content 1fr;
|
||||||
|
|
||||||
|
margin-right: -0.75rem;
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
// margin: 0 auto;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
background-color: $gray4;
|
background-color: $gray4;
|
||||||
@ -62,5 +168,26 @@ function getComponent() {
|
|||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page.noscroll {
|
||||||
|
overflow-x: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-page {
|
||||||
|
max-height: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
|
||||||
|
gap: 1.75rem 0;
|
||||||
|
|
||||||
|
padding-bottom: 4rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.load-more {
|
||||||
|
width: 10rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
<div class="noscroll">
|
<div class="noscroll">
|
||||||
<Layout :no_header="true" :tracks="search.tracks.value" />
|
<Layout :no_header="true" :tracks="search.tracks.value" />
|
||||||
</div>
|
</div>
|
||||||
<button @click.prevent="search.loadTracks">Load More</button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -18,9 +17,13 @@ const search = useSearchStore();
|
|||||||
.search-tracks-view {
|
.search-tracks-view {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
display: grid;
|
.noscroll {
|
||||||
grid-template-rows: 1fr max-content;
|
height: 100%;
|
||||||
gap: 1rem;
|
}
|
||||||
|
|
||||||
|
.header-list-layout {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user