Updated mobile player layout

This commit is contained in:
lucast committed 2026-10-06 21:23:13 +02:00
1 parent 812884de1a
commit 81b1581ed7
3 files changed
+105 -22

No files matched your search

+52 -8
View File
@@ -5,6 +5,8 @@ const { fullscreen, close: closeFullscreen } = useFullscreen()
const song = useSong() const song = useSong()
const mouseMovedRecently = ref(true) const mouseMovedRecently = ref(true)
const mobileView = ref(false) const mobileView = ref(false)
const showMobileLyrics = ref(false)
const queueOpen = useState<boolean>("queueOpen", () => false)
onMounted(() => { onMounted(() => {
let timeoutId: NodeJS.Timeout let timeoutId: NodeJS.Timeout
@@ -72,7 +74,26 @@ nuxtApp.hook("page:finish", () => {
<PlayerFullscreenTrackDisplay <PlayerFullscreenTrackDisplay
:show-buttons="mouseMovedRecently" :show-buttons="mouseMovedRecently"
/> />
<nav
v-if="mobileView"
class="mobile-tabs"
aria-label="Player views"
>
<button
:class="{ selected: showMobileLyrics }"
aria-label="Toggle lyrics"
@click="showMobileLyrics = !showMobileLyrics"
>
<Icon name="lucide:message-square-quote" />
</button>
<button aria-label="Open queue" @click="queueOpen = true">
<Icon name="lucide:list" />
</button>
</nav>
<PlayerFullscreenLyricsDisplay <PlayerFullscreenLyricsDisplay
v-if="
!mobileView || (showMobileLyrics && song.lyrics?.text)
"
:animation-duration="0.2" :animation-duration="0.2"
:offset="mobileView ? 100 : 250" :offset="mobileView ? 100 : 250"
:show-scroll-bar="mouseMovedRecently" :show-scroll-bar="mouseMovedRecently"
@@ -99,7 +120,7 @@ nuxtApp.hook("page:finish", () => {
position: fixed; position: fixed;
inset: 0; inset: 0;
background-color: rgba(0, 0, 0, 0.34); background-color: rgba(0, 0, 0, 0.34);
} }
.close-btn { .close-btn {
@@ -117,6 +138,10 @@ nuxtApp.hook("page:finish", () => {
} }
} }
.mobile-tabs {
display: none;
}
.content-container { .content-container {
/* TODO: A lot of magic numbers... should be variables */ /* TODO: A lot of magic numbers... should be variables */
max-width: 1280px; max-width: 1280px;
@@ -162,17 +187,37 @@ nuxtApp.hook("page:finish", () => {
} }
} }
.mobile-tabs {
display: flex;
justify-content: center;
gap: 3rem;
margin: 0 auto;
color: rgba(255, 255, 255, 0.72);
button {
border: 0;
padding: 0.5rem;
color: inherit;
background: transparent;
font-size: 1.5rem;
}
.selected {
color: white;
}
}
.content-container { .content-container {
max-width: none; max-width: none;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
justify-content: safe center; justify-content: space-between;
gap: 1.25rem; gap: 1.5rem;
overflow-y: auto; overflow: hidden;
overscroll-behavior: contain; padding: max(11vh, calc(2.75rem + env(safe-area-inset-top))) 1.5rem
padding: calc(3.75rem + env(safe-area-inset-top)) 1rem calc(env(safe-area-inset-bottom));
calc(1rem + env(safe-area-inset-bottom)); height: 100vh;
& > * { & > * {
max-height: none; max-height: none;
@@ -182,7 +227,6 @@ nuxtApp.hook("page:finish", () => {
&.lyrics { &.lyrics {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
} }
</style> </style>
@@ -40,9 +40,16 @@ const durationFormatted = computed(() =>
height="512" height="512"
/> />
<div class="track"> <div class="track-row">
<p class="name">{{ song.name }}</p> <div class="track">
<ArtistName :artists="song.artists" /> <p class="name">{{ song.name }}</p>
<ArtistName :artists="song.artists" />
</div>
<div class="track-actions">
<button aria-label="More track options">
<Icon name="lucide:ellipsis" />
</button>
</div>
</div> </div>
<div class="slider"> <div class="slider">
@@ -122,6 +129,31 @@ const durationFormatted = computed(() =>
} }
} }
.track-row,
.track-actions {
display: flex;
align-items: center;
}
.track-row {
width: 100%;
justify-content: space-between;
gap: 0.75rem;
}
.track-actions {
display: none;
gap: 0.75rem;
button {
border: 0;
padding: 0;
color: inherit;
background: transparent;
font-size: 1.8rem;
}
}
.slider { .slider {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -185,26 +217,33 @@ const durationFormatted = computed(() =>
@media (max-width: 767px) { @media (max-width: 767px) {
.track-display { .track-display {
gap: 0.85rem; display: contents;
}
.track-actions {
display: flex;
gap: 0.6rem;
} }
.btns { .btns {
gap: clamp(0.4rem, 3vw, 0.85rem); justify-content: space-between;
font-size: 1.75rem; gap: 0.75rem;
font-size: 2.5rem;
opacity: 1 !important;
pointer-events: auto !important;
& > :first-child,
& > :last-child {
display: none;
}
& > * { & > * {
padding: 0.45rem; padding: 0.5rem;
} }
} }
.volume-slider { .volume-slider {
margin-inline: 0; margin-inline: 0;
}
}
@media (max-width: 767px) and (hover: none) {
.btns,
.volume-slider {
opacity: 1 !important; opacity: 1 !important;
pointer-events: auto !important; pointer-events: auto !important;
} }
+1 -1
View File
@@ -43,7 +43,7 @@ const durationFormatted = computed(() =>
) )
const { open: openFullscreen } = useFullscreen() const { open: openFullscreen } = useFullscreen()
const queueOpen = ref(false) const queueOpen = useState<boolean>("queueOpen", () => false)
</script> </script>
<template> <template>