docs(09-05): complete tooltip fix plan - hover behavior and helpTextPrefix prop

- SUMMARY.md: tooltip placement fix and hover+pin behavior documented
- STATE.md: decisions added, session updated, progress at 100%
- ROADMAP.md: Phase 9 plan 5/5 complete
This commit is contained in:
2026-04-01 11:22:06 +02:00
parent d2b6da297f
commit d173fd4455
3 changed files with 128 additions and 8 deletions
@@ -0,0 +1,118 @@
---
phase: 09-md3-components
plan: "05"
subsystem: ui
tags: [react, tailwind, tooltip, accessibility, testing-library]
# Dependency graph
requires:
- phase: 09-md3-components/09-04
provides: TextFieldMD3 component with suffix/helpText props
provides:
- Tooltip hover+click behavior in FieldRenderer (text and select branches) and PasswordField
- helpTextPrefix prop on TextFieldMD3 for inline left-of-helpText slot
- Tooltip icon rendered beside helpText below the field (not above the field)
- Tests covering hover show/hide, click-pin, click-unpin, and helpTextPrefix rendering
affects: [RemoteConfigStep, PasswordField, TextFieldMD3]
# Tech tracking
tech-stack:
added: []
patterns:
- "hoverTooltip + showTooltip dual-state: hover shows, click pins, click-unpin clears both"
- "helpTextPrefix slot pattern: ReactNode prop for inline content left of helpText in TextFieldMD3"
- "Click-to-unpin guard: setShowTooltip(v => { if (v) setHoverTooltip(false); return !v; })"
key-files:
created: []
modified:
- src/components/ui/TextFieldMD3.tsx
- src/components/ui/FieldRenderer.tsx
- src/components/ui/PasswordField.tsx
- src/components/ui/FieldRenderer.test.tsx
- src/components/ui/TextFieldMD3.test.tsx
key-decisions:
- "Tooltip hover uses dual-state (hoverTooltip + showTooltip); click-unpin explicitly clears hoverTooltip to prevent sticky tooltip after dismiss"
- "helpTextPrefix guard is (helpText || helpTextPrefix) not just helpText, enabling icon-only rendering when field has tooltipText but no helpText"
- "Tooltip content rendered BELOW TextFieldMD3 (after component), not inside it — TextFieldMD3 stays self-contained"
patterns-established:
- "helpTextPrefix slot: pass ReactNode as inline prefix left of helpText text in TextFieldMD3"
- "Hover+click tooltip: mouseEnter shows, mouseLeave hides, click pins, second-click clears both states"
requirements-completed: [COMP-04]
# Metrics
duration: 10min
completed: 2026-04-01
---
# Phase 9 Plan 05: Tooltip Placement and Hover Fix Summary
**Tooltip icon moved from above field to inline with helpText below it, with hover-to-preview and click-to-pin behavior via dual hoverTooltip+showTooltip state**
## Performance
- **Duration:** ~10 min
- **Started:** 2026-04-01T09:10:00Z
- **Completed:** 2026-04-01T09:20:34Z
- **Tasks:** 2
- **Files modified:** 5
## Accomplishments
- Added `helpTextPrefix` prop to TextFieldMD3 for rendering inline content (tooltip icon) left of helpText below the field
- Fixed tooltip icon position: moved from above the floating-label input to beside helpText below it
- Implemented hover-to-preview (mouseEnter shows, mouseLeave hides) and click-to-pin (stays open through mouseLeave) in FieldRenderer and PasswordField
- Fixed click-unpin edge case: second click explicitly clears hoverTooltip so tooltip dismisses even when mouse stays on button
- Added 7 new tests covering all tooltip hover/pin/unpin behaviors and helpTextPrefix rendering
## Task Commits
Each task was committed atomically:
1. **Task 1: Add helpTextPrefix prop and fix tooltip placement + hover** - `23617c0` (feat)
2. **Task 2: Add tests for tooltip hover behavior and helpTextPrefix rendering** - `d2b6da2` (test)
## Files Created/Modified
- `src/components/ui/TextFieldMD3.tsx` - Added `helpTextPrefix?: React.ReactNode` prop; changed helpText guard to `(helpText || helpTextPrefix) && !error`; renders `<div className="flex items-start gap-1">` wrapping prefix + helpText
- `src/components/ui/FieldRenderer.tsx` - Added `hoverTooltip` state; moved tooltip icon from above-field to `tooltipIcon` element passed as `helpTextPrefix`; tooltip content rendered below TextFieldMD3; select-branch also gains hover support
- `src/components/ui/PasswordField.tsx` - Same dual-state tooltip fix as FieldRenderer text-branch
- `src/components/ui/FieldRenderer.test.tsx` - Added `fireEvent` import; added 4 hover behavior tests (hover shows, leave hides, click pins, second-click unpins)
- `src/components/ui/TextFieldMD3.test.tsx` - Added Tests 9-11 for helpTextPrefix with helpText, without, and prefix-only
## Decisions Made
- Click-to-unpin must explicitly clear `hoverTooltip` because `userEvent.click()` simulates hover before click, leaving `hoverTooltip=true` after second click — required `setShowTooltip(v => { if (v) setHoverTooltip(false); return !v; })`
- Tooltip content stays outside TextFieldMD3 (rendered after the component in FieldRenderer/PasswordField) — keeps TextFieldMD3 self-contained, tooltip is a consumer concern
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Fixed click-unpin leaving tooltip visible due to hoverTooltip race**
- **Found during:** Task 1 verification (RemoteConfigStep.test.tsx "hides tooltip panel when clicked again")
- **Issue:** `userEvent.click()` simulates mouseEnter before click; second click set `showTooltip=false` but `hoverTooltip` stayed true, so tooltip remained visible
- **Fix:** Changed click handler to `setShowTooltip(v => { if (v) setHoverTooltip(false); return !v; })` — clears hover state when unpinning
- **Files modified:** src/components/ui/FieldRenderer.tsx, src/components/ui/PasswordField.tsx
- **Verification:** All 186 tests pass including RemoteConfigStep "hides tooltip panel when clicked again"
- **Committed in:** 23617c0 (Task 1 commit)
---
**Total deviations:** 1 auto-fixed (Rule 1 - bug)
**Impact on plan:** Required for correctness — without this fix, tooltip could not be dismissed by click when mouse was over the button.
## Issues Encountered
- Click-unpin sticky tooltip: `userEvent.click` triggers hover state before click event. Resolved by clearing `hoverTooltip` in the unpin branch of the click handler.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- UAT test 7 (Tooltip Info Buttons Accessibility) now satisfies all criteria: hover shows, mouseLeave hides, click pins, click again unpins, icon beside helpText below field
- Phase 9 (09-md3-components) fully complete — all must-have truths and requirements satisfied
- Ready for Phase 10
---
*Phase: 09-md3-components*
*Completed: 2026-04-01*