# Tooltip System Plan

**Priority:** 19
**Status:** Phase 1-2 Complete, Phase 3 In Progress
**Effort:** ~4 hours
**Created:** Jan 18, 2026
**Updated:** Jan 18, 2026

---

## Goal

Add educational tooltips throughout the app that:
1. Help new users learn what each button does
2. Explain WHY to use features, not just WHAT they do
3. Can be turned OFF once users are comfortable

---

## User Setting

**"Training Wheels Mode"** - toggle in Settings

| State | Behavior |
|-------|----------|
| ON (default for new users) | Tooltips appear on hover/long-press |
| OFF | No tooltips shown |

Store in `localStorage` as `trainingWheelsEnabled` (boolean)

After 7 days of usage, prompt: "You've been using the app for a week. Want to turn off tooltips?"

---

## Chosen Approach

**Radix UI Tooltip** - Best accessibility, small bundle (~3KB), works with existing Tailwind styling.

---

## Implementation Steps

### Phase 1: Setup (~30 min) ✅ DONE
- [x] Install `@radix-ui/react-tooltip`
- [x] Create `admin/src/components/ui/Tooltip.jsx` wrapper component
- [x] Add default styling with Tailwind (dark bg, white text, arrow)
- [x] Test basic tooltip on one button

### Phase 2: Audit & Document (~30 min)
- [ ] List all icon-only buttons across the app
- [ ] Document what each button does (tooltip content)
- [ ] Prioritize high-traffic areas first

### Phase 3: Apply Educational Tooltips (~2 hours)

**Tooltip Writing Rules:**
1. Start with WHAT it does
2. Add WHY/WHEN to use it
3. Keep under 15 words
4. Use action verbs

---

**Dashboard** (PriorityActionCard.jsx)
- [ ] Message button → "Send SMS – quick way to reach leads who don't answer calls"
- [ ] Skip button → "Skip for now – moves to next lead without logging outcome"
- [ ] Score badge → "Lead score – higher means more likely to convert"
- [ ] Phone copy → "Copy number – paste into another app if needed"

**Today's Plays** (TodaysPlays.jsx)
- [ ] Send button → "Send this message – AI wrote it based on their history"
- [ ] Edit button → "Edit before sending – personalize the AI draft"
- [ ] Expand lead → "See more options – view all 3 message angles"

**Lead Profile** (LeadProfile.jsx)
- [ ] Call button → "Call now – opens dialer with their number"
- [ ] SMS button → "Send SMS – opens message composer"
- [ ] Edit button → "Edit details – update name, score, status"
- [ ] Archive button → "Archive – hide from lists but keep history"
- [ ] Recording play → "Play recording – listen to past calls for context"
- [ ] Notes button → "Add note – record important info for next call"

**Lead Action Bar** (LeadActionBar.jsx)
- [ ] SMS button → "Quick SMS – send without leaving this page"
- [ ] Playbook button → "Sales Playbook – scripts and objection handlers"
- [ ] Call button → "Call {name} – starts call with full intel loaded"
- [ ] Callback button → "Schedule callback – set reminder to call back"

**Intel Cards** (IntelSummaryCard.jsx)
- [ ] Edit button → "Edit intel – add notes or correct AI research"
- [ ] Refresh button → "Refresh – fetch latest info from web"
- [ ] Expand → "Show more – see full research details"
- [ ] Collapse → "Show less – minimize this section"

**Call List** (CallList.jsx)
- [ ] Power Dial → "Power Dialer – auto-advance through leads with study time"
- [ ] Hot filter → "Hot leads only – score 70+ most likely to convert"
- [ ] Warm filter → "Warm leads – score 50-69, need nurturing"
- [ ] Callbacks filter → "Scheduled callbacks – leads you promised to call back"
- [ ] Refresh → "Refresh list – re-rank based on latest activity"

**Bottom Navigation** (BottomNav.jsx) ✅ DONE
- [x] Dashboard → "Dashboard – your daily command center"
- [x] Call List → "Call List – AI-ranked leads to call"
- [x] Messages → "Messages – all SMS conversations"
- [x] Leads → "All Leads – search and browse everyone"
- [x] More → "More – settings, scripts, stats"

**Messages Page** (Messages.jsx)
- [ ] New message → "New message – start SMS with any lead"
- [ ] Search → "Search – find conversations by name or content"
- [ ] Mark done → "Mark handled – clears from 'Waiting on me' filter"
- [ ] Flag → "Flag – mark for follow-up later"
- [ ] AI Writer → "AI Writer – get message suggestions"

**Call Prep Page** (CallPrepPage.jsx)
- [ ] Timer → "Study timer – review intel before auto-dial"
- [ ] Pause → "Pause timer – take more time to prep"
- [ ] Call now → "Call now – skip timer and dial immediately"
- [ ] Back → "Back to list – return without calling"
- [ ] Copy opener → "Copy – paste this opening line"

**Live Copilot** (LiveCopilot.jsx)
- [ ] Suggestions → "AI detected this – tap to see suggested response"
- [ ] Thumbs up → "This helped – improves future suggestions"
- [ ] Thumbs down → "Not helpful – AI will learn from this"

**Voicemail Drop** (TwilioCall.jsx)
- [ ] VM button → "Drop voicemail – plays pre-recorded message"
- [ ] VM picker → "Choose recording – select which voicemail to leave"

### Phase 4: Polish (~30 min)
- [ ] Consistent delay (300ms) before showing
- [ ] Position tooltips to avoid edge clipping
- [ ] Test on mobile (tooltips show on long-press)
- [ ] Add keyboard accessibility (focus shows tooltip)

---

## Tooltip Component Design

### Context Provider (Global Setting)

```jsx
// admin/src/context/TooltipContext.jsx
import { createContext, useContext, useState, useEffect } from 'react';

const TooltipContext = createContext();

export function TooltipProvider({ children }) {
  const [enabled, setEnabled] = useState(() => {
    const stored = localStorage.getItem('trainingWheelsEnabled');
    // Default ON for new users
    return stored === null ? true : stored === 'true';
  });

  const [firstUseDate] = useState(() => {
    const stored = localStorage.getItem('firstUseDate');
    if (!stored) {
      const now = new Date().toISOString();
      localStorage.setItem('firstUseDate', now);
      return now;
    }
    return stored;
  });

  useEffect(() => {
    localStorage.setItem('trainingWheelsEnabled', String(enabled));
  }, [enabled]);

  // Check if 7 days have passed for prompt
  const daysSinceFirstUse = Math.floor(
    (Date.now() - new Date(firstUseDate).getTime()) / (1000 * 60 * 60 * 24)
  );
  const shouldPromptToDisable = enabled && daysSinceFirstUse >= 7;

  return (
    <TooltipContext.Provider value={{
      enabled,
      setEnabled,
      shouldPromptToDisable,
      daysSinceFirstUse
    }}>
      {children}
    </TooltipContext.Provider>
  );
}

export const useTooltips = () => useContext(TooltipContext);
```

### Tooltip Component

```jsx
// admin/src/components/ui/Tooltip.jsx
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
import { useTooltips } from '../../context/TooltipContext';

export function Tooltip({ children, content, side = 'top', delayDuration = 300 }) {
  const { enabled } = useTooltips();

  // If tooltips disabled, just render children
  if (!enabled) {
    return children;
  }

  return (
    <TooltipPrimitive.Provider>
      <TooltipPrimitive.Root delayDuration={delayDuration}>
        <TooltipPrimitive.Trigger asChild>
          {children}
        </TooltipPrimitive.Trigger>
        <TooltipPrimitive.Portal>
          <TooltipPrimitive.Content
            side={side}
            sideOffset={5}
            className="z-50 max-w-xs px-3 py-2 text-sm text-white bg-slate-900 rounded-lg shadow-lg animate-in fade-in-0 zoom-in-95"
          >
            {content}
            <TooltipPrimitive.Arrow className="fill-slate-900" />
          </TooltipPrimitive.Content>
        </TooltipPrimitive.Portal>
      </TooltipPrimitive.Root>
    </TooltipPrimitive.Provider>
  );
}
```

### Settings Toggle

```jsx
// In More.jsx or a new Settings page
import { useTooltips } from '../context/TooltipContext';
import { GraduationCap, HelpCircle } from 'lucide-react';

function TooltipSettings() {
  const { enabled, setEnabled, daysSinceFirstUse } = useTooltips();

  return (
    <div className="bg-white rounded-xl border border-slate-200 p-4">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <div className="p-2 bg-blue-50 rounded-lg">
            <GraduationCap className="w-5 h-5 text-blue-600" />
          </div>
          <div>
            <h3 className="font-medium text-slate-900">Training Wheels</h3>
            <p className="text-sm text-slate-500">
              {enabled
                ? "Hover hints explain what buttons do"
                : "Turn on to see helpful hints"
              }
            </p>
          </div>
        </div>
        <button
          onClick={() => setEnabled(!enabled)}
          className={`relative w-12 h-7 rounded-full transition-colors ${
            enabled ? 'bg-blue-600' : 'bg-slate-300'
          }`}
        >
          <span className={`absolute top-1 w-5 h-5 bg-white rounded-full shadow transition-transform ${
            enabled ? 'translate-x-6' : 'translate-x-1'
          }`} />
        </button>
      </div>
      {daysSinceFirstUse > 0 && (
        <p className="mt-2 text-xs text-slate-400">
          You've been using the app for {daysSinceFirstUse} day{daysSinceFirstUse !== 1 ? 's' : ''}
        </p>
      )}
    </div>
  );
}
```

### 7-Day Prompt Component

```jsx
// admin/src/components/TrainingWheelsPrompt.jsx
import { useTooltips } from '../context/TooltipContext';
import { useState, useEffect } from 'react';
import { GraduationCap, X } from 'lucide-react';

export function TrainingWheelsPrompt() {
  const { shouldPromptToDisable, setEnabled } = useTooltips();
  const [dismissed, setDismissed] = useState(() =>
    localStorage.getItem('trainingWheelsPromptDismissed') === 'true'
  );

  if (!shouldPromptToDisable || dismissed) return null;

  const handleDismiss = () => {
    setDismissed(true);
    localStorage.setItem('trainingWheelsPromptDismissed', 'true');
  };

  const handleTurnOff = () => {
    setEnabled(false);
    handleDismiss();
  };

  return (
    <div className="fixed bottom-20 left-4 right-4 md:left-auto md:right-4 md:w-80 bg-white rounded-xl shadow-lg border border-slate-200 p-4 z-50">
      <button
        onClick={handleDismiss}
        className="absolute top-2 right-2 p-1 text-slate-400 hover:text-slate-600"
      >
        <X className="w-4 h-4" />
      </button>
      <div className="flex items-start gap-3">
        <div className="p-2 bg-green-50 rounded-lg shrink-0">
          <GraduationCap className="w-5 h-5 text-green-600" />
        </div>
        <div>
          <h3 className="font-medium text-slate-900">Ready to go solo?</h3>
          <p className="text-sm text-slate-500 mt-1">
            You've been using the app for a week. Want to turn off the training tooltips?
          </p>
          <div className="flex gap-2 mt-3">
            <button
              onClick={handleTurnOff}
              className="px-3 py-1.5 bg-slate-900 text-white text-sm font-medium rounded-lg"
            >
              Turn off hints
            </button>
            <button
              onClick={handleDismiss}
              className="px-3 py-1.5 text-slate-600 text-sm font-medium"
            >
              Keep them
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
```

---

## Usage Example

```jsx
import { Tooltip } from '../components/ui/Tooltip';

// Before
<button onClick={handleSkip}>
  <SkipForward className="w-5 h-5" />
</button>

// After
<Tooltip content="Skip this lead">
  <button onClick={handleSkip}>
    <SkipForward className="w-5 h-5" />
  </button>
</Tooltip>
```

---

## Files to Create

| File | Purpose |
|------|---------|
| `admin/src/context/TooltipContext.jsx` | Global enabled/disabled state |
| `admin/src/components/ui/Tooltip.jsx` | Reusable tooltip wrapper |
| `admin/src/components/TrainingWheelsPrompt.jsx` | 7-day "turn off?" prompt |

## Files to Modify

| File | Changes |
|------|---------|
| `admin/package.json` | Add @radix-ui/react-tooltip |
| `admin/src/App.jsx` | Wrap with TooltipProvider |
| `admin/src/pages/More.jsx` | Add Training Wheels toggle in settings |
| `admin/src/components/dashboard/PriorityActionCard.jsx` | Wrap buttons |
| `admin/src/components/playbook/TodaysPlays.jsx` | Wrap buttons |
| `admin/src/components/LeadActionBar.jsx` | Wrap buttons |
| `admin/src/components/IntelSummaryCard.jsx` | Wrap buttons |
| `admin/src/pages/LeadProfile.jsx` | Wrap buttons |
| `admin/src/pages/CallList.jsx` | Wrap buttons |
| `admin/src/pages/CallPrepPage.jsx` | Wrap buttons |
| `admin/src/pages/Messages.jsx` | Wrap buttons |
| `admin/src/components/BottomNav.jsx` | Wrap nav items |
| `admin/src/components/LiveCopilot.jsx` | Wrap suggestion buttons |
| `admin/src/components/TwilioCall.jsx` | Wrap voicemail buttons |

---

## Success Criteria

- [ ] Every icon-only button has an educational tooltip
- [ ] Tooltips explain WHAT + WHY (not just labels)
- [ ] Tooltips appear on hover (desktop) and long-press (mobile)
- [ ] Consistent styling across all tooltips
- [ ] No layout shifts when tooltips appear
- [ ] Tooltips don't get clipped at screen edges
- [ ] Accessible via keyboard (focus shows tooltip)
- [ ] "Training Wheels" toggle in Settings works
- [ ] Setting persists across sessions (localStorage)
- [ ] 7-day prompt appears and can be dismissed
- [ ] When disabled, no tooltips render (performance)

---

## Dependencies

```bash
npm install @radix-ui/react-tooltip
```

Bundle size: ~3KB gzipped

---

## Notes

- Radix handles accessibility (ARIA attributes, keyboard nav)
- Provider can wrap entire app for global tooltip settings
- Can extend to show rich content (images, links) later if needed
- Educational content helps onboarding - key differentiator for new users
- 7-day prompt respects user growth without being annoying

---

## Implementation Summary

| Phase | Time | Deliverables |
|-------|------|--------------|
| 1. Setup | 30 min | Radix installed, Tooltip.jsx, TooltipContext.jsx |
| 2. Settings | 30 min | Toggle in More.jsx, 7-day prompt |
| 3. Audit | 30 min | List all buttons, write educational content |
| 4. Apply | 2 hr | Wrap all buttons across 12 files |
| 5. Polish | 30 min | Test mobile, keyboard, edge cases |
| **Total** | **4 hr** | Educational tooltips with Training Wheels toggle |

---

## Value Add

| Benefit | Impact |
|---------|--------|
| Faster onboarding | New users learn without asking |
| Reduced support | "What does this do?" questions eliminated |
| Professional polish | Shows attention to detail |
| User respect | They can turn it off when ready |
| Differentiation | Most apps don't explain WHY, just WHAT |
