forked from
chadtmiller.com/slices-teal-relay
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}