import Image from "next/image";
import { cn } from "@/lib/utils";
/**
* UserAvatar — the one avatar component: shows the user's image, or their
* initials on a tinted disc when there's no image. Used everywhere a user
* thumbnail appears (notification feed, comments, follower lists, and the
* profile header's large zoomable hero).
*
* Sizing is class-driven (`className`) rather than a fixed px, so callers get
* Tailwind's responsive sizes — e.g. `size-10` for a list row or
* `size-24 sm:size-28` for the profile header. `textClassName` scales the
* initials to match. When `onClick` is set, an image avatar becomes a
* focusable button (used by the profile header to open its zoom preview);
* `interactive` adds a hover-ring affordance.
*/
export function UserAvatar({
src,
name,
className,
textClassName = "text-sm",
onClick,
ariaLabel,
interactive = false,
}: {
src?: string | null;
name: string;
/** Box size + extras. Defaults to a 40px (size-10) circle. */
className?: string;
/** Initials font size — match it to the box. Defaults to text-sm. */
textClassName?: string;
/** When set, an image avatar renders as a focusable button (e.g. to open a
* zoom preview or navigate). Initials stay non-interactive. */
onClick?: () => void;
ariaLabel?: string;
/** Add a hover-ring affordance to an image avatar. */
interactive?: boolean;
}) {
const size = className ?? "size-10";
if (src) {
const imgRing = cn(
"rounded-full object-cover ring-1 ring-foreground/10",
interactive && "hover:ring-foreground/30 transition",
);
// width/height satisfy next/image; the rendered size comes from the CSS
// size class (which overrides the intrinsic attributes).
if (onClick) {
return (
);
}
return (