GRV-Summit-Site/components/home/LastYearWinnerMark.tsx
Kirubel-Kibru-Yaltopia 06936e7a4f
Some checks are pending
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Waiting to run
-
2026-05-21 21:04:53 +03:00

144 lines
4.4 KiB
TypeScript

"use client";
import { useCallback, useRef, useState } from "react";
import Image from "next/image";
import type { LastYearWinner } from "@/content/last-year-winners";
import { LastYearWinnerTip } from "@/components/home/LastYearWinnerTip";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { cn } from "@/lib/utils";
const GRV_LOGO = "/branding/logo-icon.png";
type Props = {
company: LastYearWinner;
tipKey: string;
isTipOpen: boolean;
onTipOpen: (key: string) => void;
onTipClose: () => void;
variant?: "on-green" | "on-light";
className?: string;
};
export function LastYearWinnerMark({
company,
tipKey,
isTipOpen,
onTipOpen,
onTipClose,
variant = "on-light",
className,
}: Props) {
const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
const [failed, setFailed] = useState(false);
const src = company.logoSrc ?? GRV_LOGO;
const showImage = !failed && src;
const logoOnly = !company.name;
const onLight = variant === "on-light";
const clearCloseTimer = useCallback(() => {
if (closeTimer.current) {
clearTimeout(closeTimer.current);
closeTimer.current = null;
}
}, []);
const handleEnter = useCallback(() => {
clearCloseTimer();
onTipOpen(tipKey);
}, [clearCloseTimer, onTipOpen, tipKey]);
const handleLeave = useCallback(() => {
clearCloseTimer();
closeTimer.current = setTimeout(() => onTipClose(), 120);
}, [clearCloseTimer, onTipClose]);
const handleOpenChange = useCallback(
(open: boolean) => {
if (open) onTipOpen(tipKey);
else onTipClose();
},
[onTipOpen, onTipClose, tipKey]
);
return (
<Popover open={isTipOpen} onOpenChange={handleOpenChange}>
<PopoverTrigger asChild>
<button
type="button"
className={cn(
"shrink-0 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-[#1a5c38]/40",
isTipOpen && "relative z-30"
)}
aria-label={
company.name
? `${company.name} — hover for impact details`
: "GRV alumni — hover for impact details"
}
onMouseEnter={handleEnter}
onMouseLeave={handleLeave}
onFocus={handleEnter}
onBlur={handleLeave}
>
<div
className={cn(
"flex h-10 shrink-0 items-center gap-2 rounded-lg border px-2.5 shadow-sm transition-colors",
onLight
? "border-[#1a5c38]/15 bg-white/95 hover:border-[#1a5c38]/30 hover:bg-white"
: "border-white/25 bg-white/90 hover:border-white/50 hover:bg-white",
logoOnly && "px-2",
isTipOpen &&
(onLight
? "border-[#1a5c38]/40 ring-2 ring-[#1a5c38]/15"
: "border-white/60 ring-2 ring-white/25"),
className
)}
>
<div className="relative flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md bg-white">
{showImage ? (
<Image
src={src}
alt=""
width={28}
height={28}
className="size-7 object-contain p-0.5"
onError={() => setFailed(true)}
/>
) : company.initials ? (
<span className="text-[10px] font-bold leading-none text-[#1a5c38]">
{company.initials}
</span>
) : (
<Image
src={GRV_LOGO}
alt=""
width={28}
height={28}
className="size-7 object-contain p-0.5"
/>
)}
</div>
{company.name ? (
<span className="max-w-[7.5rem] truncate text-[11px] font-medium text-[#1a5c38]">
{company.name}
</span>
) : null}
</div>
</button>
</PopoverTrigger>
{isTipOpen ? (
<PopoverContent
side="top"
align="center"
sideOffset={8}
className="z-50 border-[#1a5c38]/15 bg-white p-0 shadow-lg"
onMouseEnter={handleEnter}
onMouseLeave={handleLeave}
onOpenAutoFocus={(e) => e.preventDefault()}
>
<LastYearWinnerTip company={company} />
</PopoverContent>
) : null}
</Popover>
);
}