Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Svelte
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182<script module lang="ts"> import { tv, type VariantProps } from "tailwind-variants";
export const avatarSizeClass = { mini: "size-3.25", small: "size-4.25", regular: "size-5.25", large: "size-6.5", full: "size-full" };
export const avatar = tv({ base: "relative flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-border-default bg-background-canvas text-foreground-subtle", variants: { size: avatarSizeClass }, defaultVariants: { size: "regular" } });
export type AvatarSize = NonNullable<VariantProps<typeof avatar>["size"]>;
const sizePx = { mini: 13, small: 17, regular: 21, large: 26, full: undefined } satisfies Record<AvatarSize, number | undefined>;
export const avatarSizeNames = Object.keys(sizePx) as AvatarSize[];</script>
<script lang="ts"> import UserRound from "$icon/user-round"; import { avatarUrl } from "$lib/avatar";
interface Props { did?: string; src?: string; handle?: string; size?: AvatarSize; class?: string; }
let { did, src, handle, size = "regular", class: className = "" }: Props = $props();
const px = $derived(sizePx[size]); const source = $derived( src ?? (did ? avatarUrl(did, px === undefined ? undefined : px * 2) : undefined) );
// hidden with a style, not state, a page full of 404s would write state mid-render const hide = (event: Event) => { (event.currentTarget as HTMLImageElement).style.display = "none"; };
// a reused element has to recover from a previous failure const show = (event: Event) => { (event.currentTarget as HTMLImageElement).style.display = ""; };</script>
<span class={avatar({ size, class: className })} role={handle ? "img" : undefined} aria-label={handle ? `${handle}'s avatar` : undefined} aria-hidden={handle ? undefined : "true"}> <UserRound class="size-1/2" /> {#if source} <img src={source} alt="" class="absolute inset-0 size-full object-cover" onerror={hide} onload={show} /> {/if}</span>