@@ -6,31 +6,51 @@ interface Props {
66 name: string ;
77 link? : string ;
88}
9-
109const { avatarUrl, name, link } = Astro .props ;
1110const Tag = link ? " a" : " div" ;
11+ const initial = (name ?.trim ?.()[0 ] ?? " ?" ).toUpperCase ();
1212---
1313
1414<Tag
1515 role ={ link ? " button" : undefined }
16- class =" user-image relative flex aspect-square transform items-center justify-center overflow-auto rounded-full bg-gray-600 font-bold text-white uppercase transition-transform hover:scale-120 hover:shadow-lg"
16+ class =" user-image relative flex aspect-square items-center justify-center overflow-hidden rounded-full bg-gray-600 font-bold text-white uppercase transition-transform hover:scale-120 hover:shadow-lg"
1717 href ={ link }
1818 rel ={ link && " noreferrer" }
1919 target ={ link && " _blank" }
20+ aria-label ={ name }
21+ title ={ name }
2022>
21- { name [0 ]}
22- <RemoteResponsiveImageWrapper
23- alt ={ ` ${name }'s avatar ` }
24- src ={ avatarUrl }
25- width ={ 80 }
26- height ={ 80 }
27- class =" absolute h-full w-full bg-white object-cover"
28- />
23+ <span class =" initial pointer-events-none select-none" >{ initial } </span >
24+
25+ {
26+ avatarUrl && (
27+ <RemoteResponsiveImageWrapper
28+ alt = { ` ${name }'s avatar ` }
29+ src = { avatarUrl }
30+ width = { 80 }
31+ height = { 80 }
32+ loading = " lazy"
33+ decoding = " async"
34+ class = " absolute h-full w-full bg-white object-cover"
35+ />
36+ )
37+ }
2938</Tag >
3039
3140<style >
32- /* we have our own fallback */
33- .user-image .invalid {
34- display: none;
41+ .user-image img.invalid,
42+ .user-image img[data-fallback="true"] {
43+ display: none !important ;
3544 }
3645</style >
46+
47+ <script >
48+ const root = document.currentScript?.parentElement;
49+ const img = root?.querySelector("img");
50+ if (img) {
51+ if (!img.complete || img.naturalWidth === 0) {
52+ img.classList.add("invalid");
53+ }
54+ img.addEventListener("error", () => img.classList.add("invalid"));
55+ }
56+ </script >
0 commit comments