Teal.fm frontend powered by slices.network tealfm-slices.wisp.place
tealfm slices
1import { graphql, useFragment } from "react-relay"; 2import type { TrackItem_play$key } from "./__generated__/TrackItem_play.graphql"; 3import AlbumArt from "./AlbumArt"; 4import MusicBrainzLink from "./MusicBrainzLink"; 5 6interface TrackItemProps { 7 play: TrackItem_play$key; 8} 9 10export default function TrackItem({ play }: TrackItemProps) { 11 const data = useFragment( 12 graphql` 13 fragment TrackItem_play on FmTealAlphaFeedPlay { 14 trackName 15 playedTime 16 artists 17 releaseName 18 releaseMbId 19 actorHandle 20 musicServiceBaseDomain 21 appBskyActorProfile { 22 displayName 23 } 24 } 25 `, 26 play 27 ); 28 29 return ( 30 <div className="group py-3 px-4 hover:bg-zinc-900/50 transition-colors"> 31 <div className="flex items-center gap-4"> 32 <div className="flex-shrink-0"> 33 <AlbumArt releaseMbId={data.releaseMbId} alt={`${data.trackName} album art`} /> 34 </div> 35 36 <div className="flex-1 min-w-0 grid grid-cols-2 gap-4"> 37 <div className="min-w-0"> 38 <h3 className="text-sm font-medium text-zinc-100 truncate flex items-center gap-2"> 39 <span className="truncate">{data.trackName}</span> 40 {data.musicServiceBaseDomain === "nts.live" && ( 41 <a 42 href={`https://${data.musicServiceBaseDomain}`} 43 target="_blank" 44 rel="noopener noreferrer" 45 className="text-[10px] px-1.5 py-0.5 bg-violet-500/20 text-violet-400 rounded flex-shrink-0 hover:bg-violet-500/30 transition-colors" 46 > 47 NTS 48 </a> 49 )} 50 </h3> 51 <p className="text-xs text-zinc-500 truncate"> 52 {Array.isArray(data.artists) 53 ? data.artists.map((a) => a.artistName).join(", ") 54 : data.artists} 55 </p> 56 </div> 57 58 <div className="text-right min-w-0"> 59 <p className="text-xs text-zinc-400 truncate"> 60 <MusicBrainzLink releaseMbId={data.releaseMbId}> 61 {data.releaseName} 62 </MusicBrainzLink> 63 </p> 64 <div className="flex items-center justify-end gap-2 mt-0.5 min-w-0 overflow-hidden"> 65 {data.playedTime && ( 66 <p className="text-xs text-zinc-600 flex-shrink-0"> 67 {new Date(data.playedTime).toLocaleTimeString("en-US", { 68 hour: "numeric", 69 minute: "2-digit", 70 })} 71 </p> 72 )} 73 <a 74 href={`/profile/${data.actorHandle}`} 75 className="text-xs text-violet-500 hover:text-violet-400 transition-colors truncate block max-w-[120px]" 76 > 77 @{data.actorHandle} 78 </a> 79 </div> 80 </div> 81 </div> 82 </div> 83 </div> 84 ); 85}