A decentralized music tracking and discovery platform built on AT Protocol 🎵

Show artist genres as hashtags

Add --color-genre CSS variable for light and dark themes
Map artistResult.data.genres (previously tags) into the artist object
and render genres as hashtag spans using the new --color-genre color.
Remove Group's bottom margin and adjust the avatar/info wrapper layout.

+90 -70
+2
apps/web/src/index.css
··· 91 91 --color-button-text: #fff; 92 92 --color-skeleton-background: #f3f3f3; 93 93 --color-skeleton-foreground: #ecebeb; 94 + --color-genre: #3f03fb; 94 95 } 95 96 96 97 .dark { ··· 113 114 --color-button-text: #000; 114 115 --color-skeleton-background: #221538; 115 116 --color-skeleton-foreground: #2b1a4c; 117 + --color-genre: #00f1f3; 116 118 } 117 119 118 120 ::placeholder {
+88 -70
apps/web/src/pages/artist/Artist.tsx
··· 24 24 display: flex; 25 25 flex-direction: row; 26 26 margin-top: 20px; 27 - margin-bottom: 50px; 28 27 `; 29 28 30 29 const Artist = () => { ··· 80 79 listeners: artistResult.data.uniqueListeners, 81 80 scrobbles: artistResult.data.playCount, 82 81 picture: artistResult.data.picture, 83 - tags: artistResult.data.tags, 82 + tags: artistResult.data.genres, 84 83 uri: artistResult.data.uri, 85 84 spotifyLink: artistResult.data.spotifyLink, 86 85 }); ··· 130 129 artistResult.isLoading || 131 130 artistTracksResult.isLoading || 132 131 artistAlbumsResult.isLoading; 132 + 133 133 return ( 134 134 <Main> 135 135 <div className="pb-[100px] pt-[50px]"> 136 - <Group> 137 - <div className="mr-[20px]"> 138 - {artist?.picture && !loading && ( 139 - <Avatar name={artist?.name} src={artist?.picture} size="150px" /> 140 - )} 141 - {!artist?.picture && !loading && ( 142 - <div className="w-[150px] h-[150px] rounded-[80px] bg-[rgba(243, 243, 243, 0.725)] flex items-center justify-center"> 143 - <div 144 - style={{ 145 - height: 60, 146 - width: 60, 147 - }} 148 - > 149 - <ArtistIcon color="rgba(66, 87, 108, 0.65)" /> 150 - </div> 151 - </div> 152 - )} 153 - </div> 154 - {artist && !loading && ( 155 - <div style={{ flex: 1 }}> 156 - <HeadingMedium 157 - marginTop={"20px"} 158 - marginBottom={0} 159 - className="!text-[var(--color-text)]" 160 - > 161 - {artist?.name} 162 - </HeadingMedium> 163 - <div className="mt-[20px] flex flex-row"> 164 - <div className="mr-[20px]"> 165 - <LabelMedium 166 - margin={0} 167 - className="!text-[var(--color-text-muted)]" 136 + <div className="mb-[50px]"> 137 + <Group> 138 + <div className="mr-[20px]"> 139 + {artist?.picture && !loading && ( 140 + <Avatar 141 + name={artist?.name} 142 + src={artist?.picture} 143 + size="150px" 144 + /> 145 + )} 146 + {!artist?.picture && !loading && ( 147 + <div className="w-[150px] h-[150px] rounded-[80px] bg-[rgba(243, 243, 243, 0.725)] flex items-center justify-center"> 148 + <div 149 + style={{ 150 + height: 60, 151 + width: 60, 152 + }} 168 153 > 169 - Listeners 170 - </LabelMedium> 171 - <HeadingXSmall 172 - margin={0} 173 - className="!text-[var(--color-text)]" 174 - > 175 - {numeral(artist?.listeners).format("0,0")} 176 - </HeadingXSmall> 154 + <ArtistIcon color="rgba(66, 87, 108, 0.65)" /> 155 + </div> 177 156 </div> 178 - <div> 179 - <LabelMedium 180 - margin={0} 181 - className="!text-[var(--color-text-muted)]" 182 - > 183 - Scrobbles 184 - </LabelMedium> 185 - <HeadingXSmall 186 - margin={0} 187 - className="!text-[var(--color-text)]" 188 - > 189 - {numeral(artist?.scrobbles).format("0,0")} 190 - </HeadingXSmall> 191 - </div> 192 - <div className="flex items-center justify-end flex-1 mr-[10px]"> 193 - <a 194 - href={`https://pdsls.dev/at/${uri.replace("at://", "")}`} 195 - target="_blank" 196 - className="text-[var(--color-text)] no-underline bg-[var(--color-default-button)] rounded-[10px] p-[16px] pl-[25px] pr-[25px]" 197 - > 198 - <ExternalLink 199 - size={24} 200 - className="mr-[10px] text-[var(--color-text)]" 201 - /> 202 - View on PDSls 203 - </a> 157 + )} 158 + </div> 159 + {artist && !loading && ( 160 + <div style={{ flex: 1 }}> 161 + <HeadingMedium 162 + marginTop={"20px"} 163 + marginBottom={0} 164 + className="!text-[var(--color-text)]" 165 + > 166 + {artist?.name} 167 + </HeadingMedium> 168 + <div className="mt-[20px] flex flex-row"> 169 + <div className="mr-[20px]"> 170 + <LabelMedium 171 + margin={0} 172 + className="!text-[var(--color-text-muted)]" 173 + > 174 + Listeners 175 + </LabelMedium> 176 + <HeadingXSmall 177 + margin={0} 178 + className="!text-[var(--color-text)]" 179 + > 180 + {numeral(artist?.listeners).format("0,0")} 181 + </HeadingXSmall> 182 + </div> 183 + <div> 184 + <LabelMedium 185 + margin={0} 186 + className="!text-[var(--color-text-muted)]" 187 + > 188 + Scrobbles 189 + </LabelMedium> 190 + <HeadingXSmall 191 + margin={0} 192 + className="!text-[var(--color-text)]" 193 + > 194 + {numeral(artist?.scrobbles).format("0,0")} 195 + </HeadingXSmall> 196 + </div> 197 + <div className="flex items-center justify-end flex-1 mr-[10px]"> 198 + <a 199 + href={`https://pdsls.dev/at/${uri.replace("at://", "")}`} 200 + target="_blank" 201 + className="text-[var(--color-text)] no-underline bg-[var(--color-default-button)] rounded-[10px] p-[16px] pl-[25px] pr-[25px]" 202 + > 203 + <ExternalLink 204 + size={24} 205 + className="mr-[10px] text-[var(--color-text)]" 206 + /> 207 + View on PDSls 208 + </a> 209 + </div> 204 210 </div> 205 211 </div> 212 + )} 213 + </Group> 214 + 215 + {artist && ( 216 + <div className="mt-[30px]"> 217 + {(artist?.tags || []).map((genre) => ( 218 + <span 219 + className="mr-[15px] text-[var(--color-genre)] text-[13px]" 220 + style={{ fontFamily: "RockfordSansRegular" }} 221 + > 222 + # {genre} 223 + </span> 224 + ))} 206 225 </div> 207 226 )} 208 - </Group> 209 - 227 + </div> 210 228 <PopularSongs topTracks={topTracks} /> 211 229 <Albums topAlbums={topAlbums} /> 212 230 <ArtistListeners listeners={artistListenersResult.data} />