brackt/app/components/SportIcon.tsx
2026-05-07 16:07:34 -07:00

53 lines
1.2 KiB
TypeScript

import { useEffect, useState } from "react";
import { Trophy } from "lucide-react";
import { cn } from "~/lib/utils";
import { resolveSportIconUrl } from "~/lib/sport-icon-url";
interface SportIconProps {
sportName: string;
iconUrl?: string | null;
size?: "sm" | "md" | "lg" | "xl";
className?: string;
decorative?: boolean;
}
const sizeClasses = {
sm: "h-5 w-5",
md: "h-8 w-8",
lg: "h-12 w-12",
xl: "h-16 w-16",
};
export function SportIcon({
sportName,
iconUrl,
size = "md",
className,
decorative = false,
}: SportIconProps) {
const [failed, setFailed] = useState(false);
const resolvedIconUrl = resolveSportIconUrl(iconUrl);
useEffect(() => {
setFailed(false);
}, [resolvedIconUrl]);
if (resolvedIconUrl && !failed) {
return (
<img
src={resolvedIconUrl}
alt={decorative ? "" : sportName}
className={cn(sizeClasses[size], "shrink-0 object-contain", className)}
onError={() => setFailed(true)}
/>
);
}
return (
<Trophy
aria-hidden={decorative}
aria-label={decorative ? undefined : sportName}
className={cn(sizeClasses[size], "shrink-0 text-muted-foreground", className)}
/>
);
}