File size: 4,547 Bytes
5feba25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { useState, useRef, useEffect } from 'react'
import { Info, X } from 'lucide-react'

const FeatureTooltip = ({ feature, definition }) => {
  const [isOpen, setIsOpen] = useState(false)
  const [position, setPosition] = useState({ top: 0, left: 0 })
  const iconRef = useRef(null)
  const tooltipRef = useRef(null)

  // Handle tooltip positioning to stay visible
  useEffect(() => {
    if (!isOpen || !iconRef.current || !tooltipRef.current) return

    const calculatePosition = () => {
      const iconRect = iconRef.current.getBoundingClientRect()
      const tooltipRect = tooltipRef.current.getBoundingClientRect()

      let top = iconRect.top - 8
      let left = iconRect.right + 12

      // Adjust if tooltip goes off-screen to the right
      if (left + tooltipRect.width > window.innerWidth - 10) {
        left = iconRect.left - tooltipRect.width - 12
      }

      // Adjust if tooltip goes off-screen at the bottom
      if (top + tooltipRect.height > window.innerHeight - 10) {
        top = window.innerHeight - tooltipRect.height - 10
      }

      // Adjust if tooltip goes off-screen at the top
      if (top < 10) {
        top = 10
      }

      setPosition({ top, left })
    }

    calculatePosition()

    // Recalculate on window resize
    window.addEventListener('resize', calculatePosition)
    return () => window.removeEventListener('resize', calculatePosition)
  }, [isOpen])

  // Close tooltip when clicking outside
  useEffect(() => {
    if (!isOpen) return

    const handleClickOutside = (e) => {
      if (
        tooltipRef.current &&
        !tooltipRef.current.contains(e.target) &&
        iconRef.current &&
        !iconRef.current.contains(e.target)
      ) {
        setIsOpen(false)
      }
    }

    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [isOpen])

  const handleIconClick = (e) => {
    e.stopPropagation()
    setIsOpen(!isOpen)
  }

  const handleIconHover = (open) => {
    // Only auto-close on hover leave for desktop, not on click
    if (open) {
      setIsOpen(true)
    }
  }

  return (
    <div className="relative inline-block">
      {/* Info Icon */}
      <button
        ref={iconRef}
        onClick={handleIconClick}
        onMouseEnter={() => handleIconHover(true)}
        onMouseLeave={() => {
          // Auto-close on hover only if opened via hover (not click)
          if (!isOpen) return
          // Check if it was opened by click or hover
          const isClickOpened = isOpen && true
          // Keep it open if clicked, close if just hovered
        }}
        className="p-1 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-all duration-150 cursor-help"
        title="Click or hover for definition"
        aria-label={`Information about ${feature}`}
      >
        <Info size={14} className="flex-shrink-0" />
      </button>

      {/* Tooltip */}
      {isOpen && (
        <div
          ref={tooltipRef}
          className="fixed max-w-xs bg-slate-800 text-white rounded-lg shadow-xl p-3 text-xs leading-relaxed z-50 border border-slate-700 animate-in fade-in duration-200"
          style={{
            top: `${position.top}px`,
            left: `${position.left}px`,
          }}
        >
          {/* Header with feature name and close button */}
          <div className="flex items-start justify-between gap-2 mb-2">
            <span className="font-semibold text-slate-200">{feature}</span>
            <button
              onClick={() => setIsOpen(false)}
              className="flex-shrink-0 text-slate-400 hover:text-slate-200 transition-colors"
              aria-label="Close tooltip"
            >
              <X size={14} />
            </button>
          </div>

          {/* Definition */}
          <p className="text-slate-100 leading-relaxed">{definition}</p>

          {/* Arrow pointer (subtle) */}
          <div className="absolute w-2 h-2 bg-slate-800 border-r border-t border-slate-700 transform -translate-x-1 -top-1 left-4 rotate-45" />
        </div>
      )}

      {/* Hint text - visible on hover/click for mobile users */}
      {!isOpen && (
        <div className="absolute bottom-full right-0 mb-1 text-xs text-gray-400 whitespace-nowrap pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity">
          <span className="text-gray-400 text-[10px]">Click for info</span>
        </div>
      )}
    </div>
  )
}

export default FeatureTooltip