Skip to content

Commit 3cae084

Browse files
committed
fix: fallback image handling for sponsors
1 parent e7acdcd commit 3cae084

File tree

3 files changed

+38
-23
lines changed

3 files changed

+38
-23
lines changed

src/components/data/RemoteImageWrapper.astro

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,12 @@ if (import.meta.env.DEV) {
5151
additionalAttributes["data-image-component"] = "true";
5252
}
5353
54-
const { class: className, ...attributes } = {
55-
...additionalAttributes,
54+
const mergedClass = [additionalAttributes.class, image.attributes.class].filter(Boolean).join(" ");
55+
56+
const { class: _ignored, ...attributes } = {
5657
...image.attributes,
58+
...additionalAttributes,
5759
};
5860
---
5961

60-
{/* Applying class outside of the spread prevents it from applying unnecessary astro-* classes */}
61-
<img src={image.src} {...attributes} class={className} />
62+
<img src={image.src} {...attributes} class={mergedClass} data-fallback={additionalAttributes.class === "invalid" ? "true" : undefined} />

src/components/data/UserImage.astro

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,51 @@ interface Props {
66
name: string;
77
link?: string;
88
}
9-
109
const { avatarUrl, name, link } = Astro.props;
1110
const 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>

src/pages/sponsors.astro

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,3 @@ const sponsors = await fetchAllSponsors();
7777
</div>
7878
</section>
7979
</Layout>
80-
81-
<style>
82-
img.invalid {
83-
display: none;
84-
}
85-
</style>

0 commit comments

Comments
 (0)