From 5b7320759dd6536c8a5e51838a57aec6feb33ebf Mon Sep 17 00:00:00 2001 From: Dylan Audius Date: Fri, 29 May 2026 13:39:07 -0700 Subject: [PATCH] fix(suggested-tracks): row hover + full-row play click target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Add some tracks" rows had no visible affordance that the row is playable — only the artwork showed a play overlay on its own hover, and only the artwork accepted clicks. Move the click target to the full row (except the Add button) and surface the play overlay on row hover so the playability is obvious. - Row gets cursor:pointer, neutral hover background, and a focus-visible outline. Clicking or pressing Enter/Space anywhere on the row toggles playback (via the existing useToggleTrack hook). - Play/Pause overlay on the artwork now fades in on row hover and row focus-visible, not just artwork hover. - Add button stops propagation so it only adds, never plays. - UserLink stops propagation so clicking the artist still navigates to the profile without also triggering playback. - Skeleton row keeps a default cursor and no hover background. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../SuggestedTracks.module.css | 34 +++++++++++-- .../suggested-tracks/SuggestedTracks.tsx | 51 ++++++++++++++----- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css b/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css index e9dc06eb941..f1f2ec52f36 100644 --- a/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css +++ b/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css @@ -40,6 +40,22 @@ justify-content: space-between; padding: var(--harmony-unit-4); gap: var(--harmony-unit-3); + cursor: pointer; + transition: background-color var(--harmony-quick); +} + +.suggestedTrack:hover, +.suggestedTrack:focus-visible { + background-color: var(--harmony-n-50); +} + +.suggestedTrack:focus { + outline: none; +} + +.suggestedTrack:focus-visible { + outline: 2px solid var(--harmony-focus, var(--harmony-secondary)); + outline-offset: -2px; } .trackDetails { @@ -55,10 +71,8 @@ border: 0.5px solid var(--harmony-n-100); } -.artworkButton { - all: unset; +.artworkWrapper { position: relative; - cursor: pointer; height: var(--harmony-unit-10); width: var(--harmony-unit-10); flex-shrink: 0; @@ -74,14 +88,19 @@ background: rgba(0, 0, 0, 0.4); opacity: 0; transition: opacity var(--harmony-quick); + pointer-events: none; } -.artworkButton:hover .playOverlay, -.artworkButton:focus-visible .playOverlay, +.suggestedTrack:hover .playOverlay, +.suggestedTrack:focus-visible .playOverlay, .playOverlay.isPlaying { opacity: 1; } +.userLinkWrapper { + display: inline-flex; +} + .trackInfo { display: flex; flex-direction: column; @@ -139,4 +158,9 @@ .suggestedTrackSkeleton { composes: suggestedTrack; height: 72px; + cursor: default; +} + +.suggestedTrackSkeleton:hover { + background-color: transparent; } diff --git a/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx b/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx index ee7d02a1ba9..154a77c1cc0 100644 --- a/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx +++ b/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo } from 'react' +import { KeyboardEvent, MouseEvent, useCallback, useMemo } from 'react' import { SUGGESTED_TRACK_COUNT, @@ -79,21 +79,41 @@ const SuggestedTrackRow = (props: SuggestedTrackProps) => { onAddTrack(track_id) }, [onAddTrack, track_id]) + const handleRowKeyDown = useCallback( + (e: KeyboardEvent) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + togglePlay() + } + }, + [togglePlay] + ) + + const handleAddClick = useCallback( + (e: MouseEvent) => { + e.stopPropagation() + handleAddTrack() + }, + [handleAddTrack] + ) + return ( -
+
- +

{title}

- {user ? : null} + {user ? ( + e.stopPropagation()} + > + + + ) : null}