feat(track): show now-playing bars overlay on cover art
Docker Build & Publish / build (push) Has been cancelled
Docker Build & Publish / push (push) Has been cancelled
Docker Build & Publish / Prune old image versions (push) Has been cancelled

Overlay the accent-coloured "hopping bars" PlayingIndicator on a
track's cover art wherever TrackRow appears when it's the active
player track, and reuse the same component/overlay for the current
entry's cover in the queue panel.
This commit is contained in:
Senko-san
2026-06-13 17:49:06 +03:00
parent 3984c7a499
commit f5767ff55e
3 changed files with 47 additions and 5 deletions
+7
View File
@@ -248,7 +248,14 @@ function QueueRow({
<Icon name="dots-six-vertical" /> <Icon name="dots-six-vertical" />
</span> </span>
)} )}
<div className="qart">
<ArtTile seed={albumTitle} size={36} label={albumTitle} src={artUrl} /> <ArtTile seed={albumTitle} size={36} label={albumTitle} src={artUrl} />
{isCurrent && (
<div className="cover-playing">
<PlayingIndicator animate={isPlaying} />
</div>
)}
</div>
<div className="qt"> <div className="qt">
<div className="t">{resolved?.title ?? entry.title}</div> <div className="t">{resolved?.title ?? entry.title}</div>
<div className="r">{resolved?.artistName ?? entry.artistName}</div> <div className="r">{resolved?.artistName ?? entry.artistName}</div>
+7 -4
View File
@@ -4,6 +4,7 @@ import { TrackContextMenu } from './TrackContextMenu';
import { AvailabilityBadge } from './AvailabilityBadge'; import { AvailabilityBadge } from './AvailabilityBadge';
import { MetadataStatusBadge } from './MetadataStatusBadge'; import { MetadataStatusBadge } from './MetadataStatusBadge';
import { Icon } from '../common/Icon'; import { Icon } from '../common/Icon';
import { PlayingIndicator } from '../common/PlayingIndicator';
import { formatDuration } from '../../lib/format'; import { formatDuration } from '../../lib/format';
import { useAppDispatch, useAppSelector } from '../../hooks/useAppDispatch'; import { useAppDispatch, useAppSelector } from '../../hooks/useAppDispatch';
import { playNow } from '../../store/slices/queue'; import { playNow } from '../../store/slices/queue';
@@ -73,10 +74,7 @@ export function TrackRow({
> >
{isActive && isPlaying ? '▶' : index !== undefined ? index + 1 : ''} {isActive && isPlaying ? '▶' : index !== undefined ? index + 1 : ''}
</span> </span>
<div <div className="track-art">
className="track-art"
style={{ position: 'relative', width: 36, height: 36 }}
>
{artUrl ? ( {artUrl ? (
<img <img
src={artUrl} src={artUrl}
@@ -95,6 +93,11 @@ export function TrackRow({
}} }}
/> />
)} )}
{isActive && (
<div className="cover-playing">
<PlayingIndicator animate={isPlaying} />
</div>
)}
<button <button
type="button" type="button"
className="track-art-play" className="track-art-play"
+32
View File
@@ -955,6 +955,14 @@
/* ============================================================ /* ============================================================
TRACK ROW — cover art play overlay TRACK ROW — cover art play overlay
============================================================ */ ============================================================ */
.track-art {
position: relative;
width: 36px;
height: 36px;
flex-shrink: 0;
border-radius: 4px;
overflow: hidden;
}
.track-art-play { .track-art-play {
position: absolute; position: absolute;
inset: 0; inset: 0;
@@ -976,3 +984,27 @@
.track-art-play:hover { .track-art-play:hover {
color: var(--lime); color: var(--lime);
} }
/* Now-playing overlay shown on a cover when its track is the active one
(track lists and the queue panel both use this). */
.cover-playing {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.45);
}
.track-art:hover .cover-playing {
opacity: 0;
}
/* Queue row cover-art wrapper, sized to match the 36px ArtTile */
.qart {
position: relative;
width: 36px;
height: 36px;
flex-shrink: 0;
border-radius: 6px;
overflow: hidden;
}