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