diff --git a/docs/plans/2026-03-09-tooltip-hover-implementation.md b/docs/plans/2026-03-09-tooltip-hover-implementation.md new file mode 100644 index 0000000..b2cd640 --- /dev/null +++ b/docs/plans/2026-03-09-tooltip-hover-implementation.md @@ -0,0 +1,228 @@ +# 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** + +```typescript +// 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** + +```bash +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: +```typescript +import { attachTooltip } from './tooltip.js'; +``` + +After all tabs are created and appended to `tabContainer` (after line ~170), add: +```typescript +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** + +```bash +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: +```typescript +import { attachTooltip } from './tooltip.js'; +``` + +After the tabs are created (after line ~96, before `tabColumn.appendChild`), add: +```typescript +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** + +```bash +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): +```typescript +const STAT_FULL_NAMES: Record = { + 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: +```typescript +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** + +```bash +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**