feat: add tooltip utility for hover labels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-09 19:26:38 +00:00
parent fe7bc56c28
commit 9165758e67
+68
View File
@@ -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();
};
}