From d391f7e419c36eda4b6f5321be58e7c8fb39144c Mon Sep 17 00:00:00 2001 From: DiheChen Date: Thu, 5 Nov 2026 12:24:20 +0800 Subject: [PATCH] feat: fade covers in once they load --- web/src/shared/ui/artwork.tsx | 3 ++- web/src/shared/ui/ui.css | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/web/src/shared/ui/artwork.tsx b/web/src/shared/ui/artwork.tsx index bf2249c..ea2dd26 100644 --- a/web/src/shared/ui/artwork.tsx +++ b/web/src/shared/ui/artwork.tsx @@ -3,10 +3,11 @@ import { useState } from 'react' export function Artwork({ src, title, className = '' }: { src?: string, title: string, className?: string }) { const [failedSrc, setFailedSrc] = useState() + const [loadedSrc, setLoadedSrc] = useState() return (
{src && src !== failedSrc - ? {title} setFailedSrc(src)} /> + ? {title} setLoadedSrc(src)} onError={() => setFailedSrc(src)} /> :
) diff --git a/web/src/shared/ui/ui.css b/web/src/shared/ui/ui.css index 5776b66..0d1bed1 100644 --- a/web/src/shared/ui/ui.css +++ b/web/src/shared/ui/ui.css @@ -33,7 +33,8 @@ .skeleton-row > div > span { display: block; width: 55%; height: 12px; border-radius: 4px; background: var(--color-surface-hover); } .skeleton-row > div > span + span { width: 35%; height: 10px; margin-top: 10px; background: var(--color-surface); } .artwork { flex-shrink: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; background: var(--color-surface); color: var(--color-foreground-subtlest); border-radius: 8px; aspect-ratio: 1; } -.artwork img { width: 100%; height: 100%; object-fit: cover; } +.artwork img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 240ms ease; } +.artwork img[data-loaded] { opacity: 1; } .avatar { display: inline-grid; place-items: center; flex-shrink: 0; width: 32px; aspect-ratio: 1; overflow: hidden; border-radius: 50%; background: var(--color-accent); color: var(--color-brand); font-weight: 600; line-height: 1; } .avatar img { width: 100%; height: 100%; object-fit: cover; } .song-artwork { display: block; position: relative; flex-shrink: 0; border-radius: 8px; }