Files
dflike/docs/plans/2026-03-09-tooltip-hover-implementation.md
T
2026-03-09 19:24:17 +00:00

6.0 KiB

Tooltip Hover Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Add pixel-art styled hover tooltips to all abbreviated tab labels and stat abbreviations in the game UI.

Architecture: Create a shared tooltip utility function that creates/positions/removes tooltip divs on mouseenter/mouseleave. Both LeftPanel and NpcInfoPanel import and use it. Tooltip placement varies by context (left, right, or above).

Tech Stack: TypeScript, DOM API (no libraries)


Task 1: Create Tooltip Utility

Files:

  • Create: client/src/ui/tooltip.ts

Step 1: Create the tooltip utility module

// 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();
  };
}

Step 2: Verify it compiles

Run: npx -w client tsc --noEmit Expected: No errors

Step 3: Commit

git add client/src/ui/tooltip.ts
git commit -m "feat: add tooltip utility for hover labels"

Task 2: Add Tooltips to Left Panel Tabs

Files:

  • Modify: client/src/ui/LeftPanel.ts

Step 1: Import tooltip utility and attach tooltips to tabs

At the top of LeftPanel.ts, add:

import { attachTooltip } from './tooltip.js';

After all tabs are created and appended to tabContainer (after line ~170), add:

attachTooltip(this.statsTab, 'Superlatives', 'right');
attachTooltip(this.eventsTab, 'Event Log', 'right');
attachTooltip(this.inventionsTab, 'Inventions', 'right');
attachTooltip(this.resourcesTab, 'Resources', 'right');

Step 2: Verify it compiles

Run: npx -w client tsc --noEmit Expected: No errors

Step 3: Manual verification

Run: npm -w client run dev Hover over each left panel tab (S, E, I, R) and verify tooltips appear to the right with correct labels.

Step 4: Commit

git add client/src/ui/LeftPanel.ts
git commit -m "feat: add hover tooltips to left panel tabs"

Task 3: Add Tooltips to NPC Info Panel Tabs

Files:

  • Modify: client/src/ui/NpcInfoPanel.ts

Step 1: Import tooltip utility and attach tooltips to tabs

At the top of NpcInfoPanel.ts, add:

import { attachTooltip } from './tooltip.js';

After the tabs are created (after line ~96, before tabColumn.appendChild), add:

attachTooltip(this.statusTab, 'Status', 'left');
attachTooltip(this.relationshipsTab, 'Relationships', 'left');
attachTooltip(this.historyTab, 'History', 'left');
attachTooltip(this.inventoryTab, 'Inventory', 'left');

Step 2: Verify it compiles

Run: npx -w client tsc --noEmit Expected: No errors

Step 3: Commit

git add client/src/ui/NpcInfoPanel.ts
git commit -m "feat: add hover tooltips to NPC info panel tabs"

Task 4: Add Tooltips to Stat Abbreviations

Files:

  • Modify: client/src/ui/NpcInfoPanel.ts

Step 1: Add stat tooltip mapping and attach tooltips in setStatDisplay

Add a constant at the top of the file (after the EB object):

const STAT_FULL_NAMES: Record<string, string> = {
  STR: 'Strength', DEX: 'Dexterity', CON: 'Constitution', INT: 'Intelligence', PER: 'Perception',
  SOC: 'Sociability', COU: 'Courage', CUR: 'Curiosity', EMP: 'Empathy', TMP: 'Temperament',
};

In the setStatDisplay method, after the stat element is created (inside the if (!el) block, after this.statElements.set(label, el);), add:

if (STAT_FULL_NAMES[label]) {
  attachTooltip(el, STAT_FULL_NAMES[label], 'above');
}

Step 2: Verify it compiles

Run: npx -w client tsc --noEmit Expected: No errors

Step 3: Commit

git add client/src/ui/NpcInfoPanel.ts
git commit -m "feat: add hover tooltips to stat abbreviations"

Task 5: Visual QA

Step 1: Start the client and server

Run: npm -w server run dev and npm -w client run dev

Step 2: Verify all tooltips

  • Hover over each left panel tab (S, E, I, R) — tooltips appear to the right
  • Follow an NPC, hover over each right panel tab (S, R, H, I) — tooltips appear to the left
  • Hover over each stat abbreviation (STR, DEX, etc.) — tooltips appear above
  • Verify tooltips disappear when mouse leaves
  • Verify tooltip styling matches the game aesthetic (pixel font, dark background, purple border)

Step 3: Final commit if any fixes needed