diff --git a/client/src/ui/tooltip.ts b/client/src/ui/tooltip.ts new file mode 100644 index 0000000..80b4940 --- /dev/null +++ b/client/src/ui/tooltip.ts @@ -0,0 +1,68 @@ +// Tooltip positioning options +type TooltipPosition = 'left' | 'right' | 'above'; + +const TOOLTIP_STYLE = ` + position: absolute; + background: #1a1a2e; + border: 2px solid #7878d8; + color: #e0d0b0; + font-family: 'Press Start 2P', monospace; + font-size: 10px; + padding: 4px 8px; + white-space: nowrap; + pointer-events: none; + z-index: 10000; +`; + +/** + * Attach a hover tooltip to an element. + * Returns a cleanup function to remove the listeners. + */ +export function attachTooltip( + element: HTMLElement, + text: string, + position: TooltipPosition = 'right', +): () => void { + let tooltip: HTMLDivElement | null = null; + + const show = () => { + tooltip = document.createElement('div'); + tooltip.style.cssText = TOOLTIP_STYLE; + tooltip.textContent = text; + document.body.appendChild(tooltip); + + const rect = element.getBoundingClientRect(); + const tipRect = tooltip.getBoundingClientRect(); + + switch (position) { + case 'right': + tooltip.style.left = `${rect.right + 6}px`; + tooltip.style.top = `${rect.top + (rect.height - tipRect.height) / 2}px`; + break; + case 'left': + tooltip.style.left = `${rect.left - tipRect.width - 6}px`; + tooltip.style.top = `${rect.top + (rect.height - tipRect.height) / 2}px`; + break; + case 'above': + tooltip.style.left = `${rect.left + (rect.width - tipRect.width) / 2}px`; + tooltip.style.top = `${rect.top - tipRect.height - 6}px`; + break; + } + }; + + const hide = () => { + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + }; + + element.addEventListener('mouseenter', show); + element.addEventListener('mouseleave', hide); + + return () => { + element.removeEventListener('mouseenter', show); + element.removeEventListener('mouseleave', hide); + hide(); + }; +}