47 lines
1.2 KiB
TypeScript
Raw Normal View History

2026-06-22 14:43:46 +08:00
'use client';
import { useState } from 'react';
import { cn, resolveUploadUrl } from '@/lib/utils';
interface AvatarProps {
src?: string | null;
name?: string | null;
size?: number;
className?: string;
}
/**
* src onError
*/
export function Avatar({ src, name, size = 32, className }: AvatarProps) {
const [imgError, setImgError] = useState(false);
const showImg = Boolean(src) && !imgError;
const initial = (name?.trim()?.charAt(0) ?? '?').toUpperCase();
const fontSize = Math.max(12, Math.round(size * 0.45));
if (showImg) {
return (
// eslint-disable-next-line @next/next/no-img-element
<img
src={resolveUploadUrl(src ?? '')}
alt={name ?? 'avatar'}
onError={() => setImgError(true)}
style={{ width: size, height: size }}
className={cn('rounded-full object-cover', className)}
/>
);
}
return (
<div
style={{ width: size, height: size, fontSize }}
className={cn(
'flex shrink-0 items-center justify-center rounded-full bg-brand-600 font-medium text-white',
className,
)}
>
{initial}
</div>
);
}