All files / components/ui avatar.tsx

0% Statements 0/9
0% Branches 0/11
0% Functions 0/1
0% Lines 0/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80                                                                                                                                                               
import { cn } from "@/utils/class-name";
import {
  APP_ASSISTANT_AVATAR_ALT,
  APP_ASSISTANT_AVATAR_SRC,
} from "@/constants/app";
 
const SIZE = {
  sm: { box: "h-[30px] w-[30px]", text: "text-[10px] tracking-wide" },
  md: { box: "h-9 w-9",           text: "text-[11px] tracking-wide" },
  lg: { box: "h-14 w-14",         text: "text-sm tracking-wider"    },
} as const;
 
export type AvatarSize = keyof typeof SIZE;
 
const BASE =
  "relative shrink-0 select-none overflow-hidden rounded-full bg-cover bg-center";
 
type AvatarProps =
  | { variant: "assistant"; size?: AvatarSize; className?: string }
  | {
      variant: "user";
      src?: string;
      alt: string;
      initials: string;
      size?: AvatarSize;
      className?: string;
    };
 
export function Avatar(props: AvatarProps) {
  if (props.variant === "assistant") {
    const { size = "sm", className } = props;
    return (
      <div
        role="img"
        aria-label={APP_ASSISTANT_AVATAR_ALT}
        className={cn(
          BASE,
          SIZE[size].box,
          "border border-white/20 shadow-[0_2px_8px_rgba(0,0,0,0.35),0_0_0_1px_rgba(124,58,237,0.18)]",
          className,
        )}
        style={{
          backgroundImage: `url(${APP_ASSISTANT_AVATAR_SRC}), linear-gradient(135deg,#7c3aed 0%,#06b6d4 100%)`,
        }}
      />
    );
  }
 
  const { src, alt, initials, size = "sm", className } = props;
  const hasImage = Boolean(src?.trim());
 
  return (
    <div
      role="img"
      aria-label={alt}
      className={cn(
        BASE,
        SIZE[size].box,
        "bg-[radial-gradient(circle_at_30%_30%,rgba(99,102,241,0.45),rgba(109,40,217,0.35))]",
        "ring-[1.5px] ring-indigo-400/35",
        !hasImage && "shadow-[inset_0_1px_0_rgba(255,255,255,0.12),0_2px_6px_rgba(0,0,0,0.25)]",
        hasImage && "shadow-[0_2px_6px_rgba(0,0,0,0.3)]",
        className,
      )}
      style={hasImage ? { backgroundImage: `url(${src})` } : undefined}
    >
      {hasImage ? null : (
        <span
          className={cn(
            "absolute inset-0 flex items-center justify-center font-dm-sans font-semibold text-white/90",
            SIZE[size].text,
          )}
        >
          {initials}
        </span>
      )}
    </div>
  );
}