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 appBskyActorProfile { 21 displayName 22 } 23 } 24 `, 25 play 26 ); 27 28 return ( 29 <div className="group py-3 px-4 hover:bg-zinc-900/50 transition-colors"> 30 <div className="flex items-center gap-4"> 31 <div className="flex-shrink-0"> 32 <AlbumArt releaseMbId={data.releaseMbId} alt={`${data.trackName} album art`} /> 33 </div> 34 35 <div className="flex-1 min-w-0 grid grid-cols-2 gap-4"> 36 <div className="min-w-0"> 37 <h3 className="text-sm font-medium text-zinc-100 truncate"> 38 {data.trackName} 39 </h3> 40 <p className="text-xs text-zinc-500 truncate"> 41 {Array.isArray(data.artists) 42 ? data.artists.map((a) => a.artistName).join(", ") 43 : data.artists} 44 </p> 45 </div> 46 47 <div className="text-right min-w-0"> 48 <p className="text-xs text-zinc-400 truncate"> 49 <MusicBrainzLink releaseMbId={data.releaseMbId}> 50 {data.releaseName} 51 </MusicBrainzLink> 52 </p> 53 <div className="flex items-center justify-end gap-2 mt-0.5 min-w-0 overflow-hidden"> 54 {data.playedTime && ( 55 <p className="text-xs text-zinc-600 flex-shrink-0"> 56 {new Date(data.playedTime).toLocaleTimeString("en-US", { 57 hour: "numeric", 58 minute: "2-digit", 59 })} 60 </p> 61 )} 62 <a 63 href={`/profile/${data.actorHandle}`} 64 className="text-xs text-violet-500 hover:text-violet-400 transition-colors truncate block max-w-[120px]" 65 > 66 @{data.actorHandle} 67 </a> 68 </div> 69 </div> 70 </div> 71 </div> 72 </div> 73 ); 74}