// Reusable avatar that prefers an uploaded image and falls back to a coloured
// letter circle. Use this everywhere the app needs to render a profile.
import { useCachedAvatarUrl } from '../lib/avatarCache';
interface Props {
url?: string | null | undefined;
displayName?: string | null | undefined;
className?: string;
// Background gradient classes used when no image is set. Defaults to a
// brand-tinted fallback; callers can override (e.g. to colour-by-id).
fallbackClass?: string;
alt?: string;
// Browser loading hint. Use 'eager' for above-the-fold avatars (e.g. the
// active conversation header, call tiles). Defaults to 'lazy' so off-screen
// avatars (chat list rows, friends list, popovers) don't hammer Supabase
// Storage on initial render.
loading?: 'eager' | 'lazy';
}
export function Avatar({
url,
displayName,
className = 'h-10 w-10',
fallbackClass = 'bg-accent/20 text-accent',
alt,
loading = 'lazy',
}: Props) {
const effectiveUrl = useCachedAvatarUrl(url);
if (effectiveUrl) {
return (
);
}
const letter = (displayName ?? '?').trim().charAt(0).toUpperCase() || '?';
return (