Avatar.tsx
Raw
1// 1×1 transparent GIF — used as img fallback so the browser never enters
2// broken-image state while waiting for the JXL polyfill to decode the source.
3const TRANSPARENT =
4 "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
5
6export function Avatar({
7 userId,
8 version,
9 size = 32,
10}: {
11 userId: number | null;
12 version?: number | null;
13 size?: number;
14}) {
15 const style = `width:${size}px;height:${size}px`;
16 if (!userId) {
17 return (
18 <span
19 class="avatar avatar-placeholder"
20 style={`${style};font-size:${Math.round(size * 0.45)}px`}
21 >
22 ?
23 </span>
24 );
25 }
26 const src =
27 version != null
28 ? `/avatars/${userId}.jxl?v=${version}`
29 : `/avatars/${userId}.jxl`;
30 return (
31 <picture class="avatar" style={style}>
32 <source srcset={src} type="image/jxl" />
33 <img
34 src={TRANSPARENT}
35 alt=""
36 width={String(size)}
37 height={String(size)}
38 class="avatar-img"
39 />
40 </picture>
41 );
42}
43