Improved mobile search experience

This commit is contained in:
lucast committed 2026-10-06 04:08:50 +02:00
1 parent 1fce02ad84
commit ce0bf50223
5 files changed
+244 -24

No files matched your search

+59 -1
View File
@@ -30,7 +30,16 @@ const entryType = computed(() =>
<template>
<article class="search-row" :class="{ odd: props.index % 2 === 1 }">
<div class="artwork" @click="props.result.type === 'track' && emit('play')">
<div
class="artwork"
:class="{ playable: props.result.type === 'track' }"
:role="props.result.type === 'track' ? 'button' : undefined"
:tabindex="props.result.type === 'track' ? 0 : undefined"
:aria-label="props.result.type === 'track' ? `Play ${props.result.name}` : undefined"
@click="props.result.type === 'track' && emit('play')"
@keydown.enter.prevent="props.result.type === 'track' && emit('play')"
@keydown.space.prevent="props.result.type === 'track' && emit('play')"
>
<NuxtImg
v-if="artworkSrc"
:src="artworkSrc"
@@ -93,6 +102,10 @@ const entryType = computed(() =>
justify-content: center;
border-radius: $border-radius-standard;
cursor: pointer;
border: 0;
padding: 0;
color: inherit;
background: transparent;
img {
max-width: 100%;
@@ -140,4 +153,49 @@ const entryType = computed(() =>
.artists {
min-width: 0;
}
@media (max-width: 767px) {
.search-row {
grid-template-columns: 40px minmax(0, 1fr);
grid-template-areas:
"art details"
"art artists";
column-gap: 0.75rem;
row-gap: 0.25rem;
padding-inline: 0.75rem;
}
.artwork {
grid-area: art;
&.playable .play-icon {
opacity: 1;
padding: 0.5rem;
border-radius: 50%;
background: rgb(0 0 0 / 55%);
}
}
.details {
grid-area: details;
min-width: 0;
}
.artists {
grid-area: artists;
overflow-wrap: anywhere;
:deep(.artist-name) {
min-width: 0;
}
:deep(.artist-name a) {
overflow-wrap: anywhere;
}
}
.search-row > span:last-child {
display: none;
}
}
</style>
+4 -1
View File
@@ -112,7 +112,10 @@ const visibleDropdownMenuItems = computed(() =>
<ArtistName :artists="track.artists" class="artists" />
</div>
<DropdownMenu :items="visibleDropdownMenuItems">
<DropdownMenu
:items="visibleDropdownMenuItems"
:label="`Options for ${track.name}`"
>
<Icon name="lucide:ellipsis" class="dropdown-icon" />
</DropdownMenu>
</article>
+33 -1
View File
@@ -15,6 +15,7 @@ interface TrackRowProps {
extendedInfo?: boolean
showImage?: boolean
queueMode?: boolean
touchFriendly?: boolean
}
const props = defineProps<TrackRowProps>()
@@ -140,7 +141,21 @@ const artworkSrc = computed(() => {
v-if="props.track"
name="lucide:play"
class="play-icon"
:class="{ 'touch-friendly': props.touchFriendly }"
:role="props.touchFriendly ? 'button' : undefined"
:tabindex="props.touchFriendly ? 0 : undefined"
:aria-label="
props.touchFriendly
? `Play ${props.track.name}`
: undefined
"
@click="emit('playAlbumAtIndex')"
@keydown.enter.prevent="
props.touchFriendly && emit('playAlbumAtIndex')
"
@keydown.space.prevent="
props.touchFriendly && emit('playAlbumAtIndex')
"
/>
<!-- Keep the existing TrackRow artwork dimensions unchanged. -->
<NuxtImg
@@ -194,7 +209,11 @@ const artworkSrc = computed(() => {
class="queue-handle"
aria-hidden="true"
/>
<DropdownMenu v-else-if="props.track" :items="visibleDropdownMenuItems">
<DropdownMenu
v-else-if="props.track"
:items="visibleDropdownMenuItems"
:label="`Options for ${props.track.name}`"
>
<Icon name="lucide:ellipsis" class="dropdown-icon" />
</DropdownMenu>
</article>
@@ -274,6 +293,10 @@ const artworkSrc = computed(() => {
opacity: 0;
z-index: 1;
font-size: 24px;
&:focus-visible {
opacity: 1;
}
}
.play-icon.inline {
@@ -298,6 +321,15 @@ const artworkSrc = computed(() => {
}
}
@media (max-width: 767px) {
.play-icon.touch-friendly {
opacity: 1;
padding: 0.5rem;
border-radius: 50%;
background: rgb(0 0 0 / 55%);
}
}
.artists {
opacity: 1;
}