import { useState, useRef, useEffect } from 'react' import { createPortal } from 'react-dom' import { CheckCircle, Circle, Info, X } from 'lucide-react' /** * MetricItem Component * * Handles individual health metric with isolated hover state * Uses React Portal to render popover outside the scrollable sidebar * Ensures popover floats over the chat area without being clipped */ const MetricItem = ({ feature, displayLabel, definition, isCollected }) => { const [showHint, setShowHint] = useState(false) const [popoverPosition, setPopoverPosition] = useState({ top: 0, left: 0 }) const iconRef = useRef(null) // Calculate popover position based on icon location useEffect(() => { if (!showHint || !iconRef.current) return const iconRect = iconRef.current.getBoundingClientRect() // Position popover to the right of the icon, aligned with top // Add some spacing (16px) to the right const left = iconRect.right + 16 const top = iconRect.top - 8 // Slight vertical centering setPopoverPosition({ top, left }) }, [showHint]) // Handle mouse leaving the metric item const handleMouseLeave = () => { setShowHint(false) } // Handle mouse entering the metric item const handleMouseEnter = () => { setShowHint(true) } // Close hint when clicking X button const handleCloseHint = (e) => { e.stopPropagation() setShowHint(false) } return ( <> {/* Metric Item Row */}
{/* Status icon + Label */}
{isCollected ? ( ) : ( )} {displayLabel}
{/* Info Icon Button */}
{/* Popover - Rendered via Portal (outside sidebar) with Glassmorphism */} {showHint && createPortal(
setShowHint(true)} onMouseLeave={() => setShowHint(false)} > {/* Header with feature name and close button */}
{displayLabel}
{/* Definition text */}

{definition}

{/* Arrow pointer - points back to info icon (matches popover styling) */}
, document.body )} ) } export default MetricItem