({
className,
text,
position,
children,
offset,
}: Props)
| 25 | } |
| 26 | |
| 27 | export default function Tooltip({ |
| 28 | className, |
| 29 | text, |
| 30 | position, |
| 31 | children, |
| 32 | offset, |
| 33 | }: Props) { |
| 34 | const [coords, setCoords] = useState({ left: 0, top: 0 }); |
| 35 | const [show, toggle] = useState(false); |
| 36 | |
| 37 | const onMouseEnter = (event: React.MouseEvent<HTMLDivElement>) => { |
| 38 | const node = event.currentTarget as HTMLDivElement; |
| 39 | const rect = node.getBoundingClientRect(); |
| 40 | setCoords(calculateCoords(rect, position as string, offset as number)); |
| 41 | toggle(true); |
| 42 | }; |
| 43 | |
| 44 | const onMouseLeave = () => { |
| 45 | toggle(false); |
| 46 | }; |
| 47 | return ( |
| 48 | <> |
| 49 | <div |
| 50 | className={className} |
| 51 | onMouseEnter={onMouseEnter} |
| 52 | onMouseLeave={onMouseLeave} |
| 53 | > |
| 54 | {children} |
| 55 | </div> |
| 56 | {show && ( |
| 57 | <Portal id="tooltip-portal"> |
| 58 | <div |
| 59 | style={{ left: coords.left, top: coords.top }} |
| 60 | className={classNames(styles.tooltip, { |
| 61 | [styles.top]: position === 'top', |
| 62 | [styles.right]: position === 'right', |
| 63 | })} |
| 64 | > |
| 65 | {text} |
| 66 | </div> |
| 67 | </Portal> |
| 68 | )} |
| 69 | </> |
| 70 | ); |
| 71 | } |
| 72 | |
| 73 | Tooltip.defaultProps = { |
| 74 | position: 'top', |
nothing calls this directly
no outgoing calls
no test coverage detected