Update album component motion and interaction
This commit is contained in:
parent
188e95f597
commit
1bbc4260de
2 changed files with 58 additions and 14 deletions
|
|
@ -9,33 +9,41 @@
|
|||
|
||||
interface AlbumProps {
|
||||
album?: Album
|
||||
albumId?: string
|
||||
hoveredAlbumId?: string | null
|
||||
onHover?: (albumId: string | null) => void
|
||||
}
|
||||
|
||||
let { album = undefined }: AlbumProps = $props()
|
||||
let { album = undefined, albumId = '', hoveredAlbumId = null, onHover }: AlbumProps = $props()
|
||||
|
||||
let isHovering = $state(false)
|
||||
let audio: HTMLAudioElement | null = $state(null)
|
||||
|
||||
// Create a unique ID for this album
|
||||
const albumId = $derived(album ? `${album.artist.name}-${album.name}` : '')
|
||||
// Create a unique ID for this album if not provided
|
||||
const currentAlbumId = $derived(albumId || (album ? `${album.artist.name}-${album.name}` : ''))
|
||||
|
||||
// Subscribe to the store to know if this album is playing
|
||||
let isPlaying = $state(false)
|
||||
$effect(() => {
|
||||
const unsubscribe = audioPreview.subscribe((state) => {
|
||||
isPlaying = state.currentAlbumId === albumId && state.isPlaying
|
||||
isPlaying = state.currentAlbumId === currentAlbumId && state.isPlaying
|
||||
})
|
||||
return unsubscribe
|
||||
})
|
||||
|
||||
const scale = new Spring(1, {
|
||||
stiffness: 0.1,
|
||||
damping: 0.25
|
||||
stiffness: 0.2,
|
||||
damping: 0.12
|
||||
})
|
||||
|
||||
// Determine if this album should shrink
|
||||
const shouldShrink = $derived(hoveredAlbumId !== null && hoveredAlbumId !== currentAlbumId)
|
||||
|
||||
$effect(() => {
|
||||
if (isHovering) {
|
||||
scale.target = 1.1
|
||||
} else if (shouldShrink) {
|
||||
scale.target = 0.95
|
||||
} else {
|
||||
scale.target = 1
|
||||
}
|
||||
|
|
@ -57,7 +65,7 @@
|
|||
audioPreview.stop()
|
||||
} else {
|
||||
// Update the store first, then play
|
||||
audioPreview.play(audio, albumId)
|
||||
audioPreview.play(audio, currentAlbumId)
|
||||
try {
|
||||
await audio.play()
|
||||
} catch (error) {
|
||||
|
|
@ -111,8 +119,14 @@
|
|||
href={album.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onmouseenter={() => (isHovering = true)}
|
||||
onmouseleave={() => (isHovering = false)}
|
||||
onmouseenter={() => {
|
||||
isHovering = true
|
||||
onHover?.(currentAlbumId)
|
||||
}}
|
||||
onmouseleave={() => {
|
||||
isHovering = false
|
||||
onHover?.(null)
|
||||
}}
|
||||
>
|
||||
<div class="artwork-container">
|
||||
<img
|
||||
|
|
@ -124,9 +138,10 @@
|
|||
{#if isNowPlaying}
|
||||
<NowPlaying trackName={nowPlayingTrack !== album.name ? nowPlayingTrack : undefined} />
|
||||
{/if}
|
||||
{#if hasPreview && isHovering}
|
||||
{#if hasPreview && (isHovering || isPlaying)}
|
||||
<button
|
||||
class="preview-button"
|
||||
class:corner={isPlaying && !isHovering}
|
||||
onclick={togglePreview}
|
||||
aria-label={isPlaying ? 'Pause preview' : 'Play preview'}
|
||||
class:playing={isPlaying}
|
||||
|
|
@ -206,12 +221,26 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
&.corner {
|
||||
top: auto;
|
||||
left: $unit * 1.5;
|
||||
bottom: $unit-2x;
|
||||
transform: none;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
transform: translate(-50%, -50%) scale(1.1);
|
||||
|
||||
&.corner {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
&.playing {
|
||||
|
|
|
|||
|
|
@ -2,15 +2,30 @@
|
|||
import Album from '$components/Album.svelte'
|
||||
import type { Album as AlbumType } from '$lib/types/lastfm'
|
||||
|
||||
export let albums: AlbumType[] = []
|
||||
interface RecentAlbumsProps {
|
||||
albums?: AlbumType[]
|
||||
}
|
||||
|
||||
let { albums = [] }: RecentAlbumsProps = $props()
|
||||
|
||||
let hoveredAlbumId: string | null = $state(null)
|
||||
|
||||
function handleAlbumHover(albumId: string | null) {
|
||||
hoveredAlbumId = albumId
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="recent-albums">
|
||||
{#if albums.length > 0}
|
||||
<ul>
|
||||
{#each albums.slice(0, 4) as album}
|
||||
{#each albums.slice(0, 4) as album, index}
|
||||
<li>
|
||||
<Album {album} />
|
||||
<Album
|
||||
{album}
|
||||
albumId={`${album.artist.name}-${album.name}`}
|
||||
{hoveredAlbumId}
|
||||
onHover={handleAlbumHover}
|
||||
/>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
|
|
|||
Loading…
Reference in a new issue