Files
multica/packages/ui/components/common/actor-avatar.tsx
Qi Yijiazhen d9ae891064 fix(avatar): stop bg-muted bleeding through transparent images (#2670)
ActorAvatar applies bg-muted on its container regardless of whether
an image is loaded, so transparent regions of PNG/SVG avatars reveal
the grey placeholder. agent-detail-inspector also wraps ActorAvatar
in an outer bg-muted div, layering a second grey square.

Make bg-muted conditional on the fallback state in ActorAvatar, and
drop the redundant bg-muted from avatar-picker's image-loaded branch
and the two inspector wrappers. Empty-state placeholders unchanged.
2026-05-18 18:23:46 +08:00

70 lines
1.7 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { Bot, Users } from "lucide-react";
import { cn } from "@multica/ui/lib/utils";
import { MulticaIcon } from "./multica-icon";
interface ActorAvatarProps {
name: string;
initials: string;
avatarUrl?: string | null;
isAgent?: boolean;
isSystem?: boolean;
isSquad?: boolean;
size?: number;
className?: string;
}
function ActorAvatar({
name,
initials,
avatarUrl,
isAgent,
isSystem,
isSquad,
size = 20,
className,
}: ActorAvatarProps) {
const [imgError, setImgError] = useState(false);
useEffect(() => {
setImgError(false);
}, [avatarUrl]);
return (
<div
data-slot="avatar"
className={cn(
"inline-flex shrink-0 items-center justify-center font-medium overflow-hidden",
// Squads (a group, non-human) get a square tile so they don't read as
// a single person; everyone else stays round.
isSquad ? "rounded-md" : "rounded-full",
(!avatarUrl || imgError) && "bg-muted text-muted-foreground",
className
)}
style={{ width: size, height: size, fontSize: size * 0.45 }}
title={name}
>
{avatarUrl && !imgError ? (
<img
src={avatarUrl}
alt={name}
className="h-full w-full object-cover"
onError={() => setImgError(true)}
/>
) : isSystem ? (
<MulticaIcon noSpin style={{ width: size * 0.55, height: size * 0.55 }} />
) : isAgent ? (
<Bot style={{ width: size * 0.55, height: size * 0.55 }} />
) : isSquad ? (
<Users style={{ width: size * 0.55, height: size * 0.55 }} />
) : (
initials
)}
</div>
);
}
export { ActorAvatar, type ActorAvatarProps };