--- phase: 09-md3-components plan: 05 type: execute wave: 1 depends_on: ["09-04"] files_modified: - src/components/ui/TextFieldMD3.tsx - src/components/ui/TextFieldMD3.test.tsx - src/components/ui/FieldRenderer.tsx - src/components/ui/FieldRenderer.test.tsx - src/components/ui/PasswordField.tsx autonomous: true gap_closure: true requirements: [COMP-04] must_haves: truths: - "Hovering the tooltip info button reveals tooltip text without clicking" - "Clicking the tooltip info button pins it open; clicking again dismisses it" - "Tooltip icon appears beside the helpText below the field, not above the field" artifacts: - path: "src/components/ui/TextFieldMD3.tsx" provides: "helpTextPrefix prop for rendering inline content left of helpText" contains: "helpTextPrefix" - path: "src/components/ui/FieldRenderer.tsx" provides: "Tooltip icon passed as helpTextPrefix, hover+click behavior" contains: "onMouseEnter" - path: "src/components/ui/PasswordField.tsx" provides: "Same tooltip fix as FieldRenderer text-branch" contains: "onMouseEnter" key_links: - from: "src/components/ui/FieldRenderer.tsx" to: "src/components/ui/TextFieldMD3.tsx" via: "helpTextPrefix prop" pattern: "helpTextPrefix.*ⓘ" - from: "src/components/ui/PasswordField.tsx" to: "src/components/ui/TextFieldMD3.tsx" via: "helpTextPrefix prop" pattern: "helpTextPrefix.*ⓘ" --- Fix two UAT-reported tooltip issues: (1) tooltip doesn't show on hover, only on click; (2) tooltip icon is positioned above the field instead of beside the helpText below it. Purpose: Close the last remaining UAT gap in Phase 9 (test 7: Tooltip Info Buttons Accessibility). Output: Tooltip icon renders inline with helpText below the field, and tooltip text appears on hover (pinnable via click). @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/09-md3-components/09-03-SUMMARY.md From src/components/ui/TextFieldMD3.tsx: ```typescript interface TextFieldMD3Props { id: string; label: string; error?: FieldError; registration: UseFormRegisterReturn; type?: 'text' | 'password'; helpText?: string; required?: boolean; suffix?: React.ReactNode; } ``` From src/components/ui/FieldRenderer.tsx: ```typescript // text (default) — uses TextFieldMD3 for floating label return (
{field.tooltipText && ( )} {field.tooltipText && showTooltip && (

{field.tooltipText}

)}
); ``` ```typescript {helpText && !error && (

{helpText}

)} ```
Task 1: Add helpTextPrefix prop to TextFieldMD3 and fix tooltip placement + hover in FieldRenderer and PasswordField src/components/ui/TextFieldMD3.tsx, src/components/ui/FieldRenderer.tsx, src/components/ui/PasswordField.tsx **TextFieldMD3.tsx — Add helpTextPrefix prop:** 1. Add `helpTextPrefix?: React.ReactNode` to `TextFieldMD3Props` interface. 2. Destructure `helpTextPrefix` in the component function. 3. Change the helpText rendering block (lines 65-67) from: ```tsx {helpText && !error && (

{helpText}

)} ``` To: ```tsx {helpText && !error && (
{helpTextPrefix}

{helpText}

)} ``` This renders optional inline content (the tooltip icon) to the left of helpText. When `helpTextPrefix` is undefined/null, the flex container still renders correctly with just the `

`. **FieldRenderer.tsx — Fix text-branch tooltip (lines 83-109):** 1. Remove the tooltip ` ) : undefined; ``` 4. Compute tooltip visibility: `const tooltipVisible = showTooltip || hoverTooltip`. 5. Render the tooltip content BELOW TextFieldMD3 (after the component, inside the flex-col wrapper), conditioned on `tooltipVisible`: ```tsx {field.tooltipText && tooltipVisible && (

{field.tooltipText}

)} ``` 6. Pass `helpTextPrefix={tooltipIcon}` to TextFieldMD3. 7. The final text-branch return should look like: ```tsx return (
{field.tooltipText && tooltipVisible && (

{field.tooltipText}

)}
); ``` **FieldRenderer.tsx — Fix select-branch tooltip (lines 40-78):** The select branch also has a tooltip button. Apply the same hover fix to the select branch: 1. Add `onMouseEnter={() => setHoverTooltip(true)}` and `onMouseLeave={() => setHoverTooltip(false)}` to the existing select-branch tooltip button (line 51). 2. Change the tooltip content visibility condition from `showTooltip` to `tooltipVisible` (line 59). 3. The select branch does NOT use TextFieldMD3, so no `helpTextPrefix` needed there — keep the icon in its current position above the select (it already has a visible label, not a floating label). **PasswordField.tsx — Same fix as FieldRenderer text-branch:** 1. Add `const [hoverTooltip, setHoverTooltip] = useState(false)` alongside existing `showTooltip`. 2. Remove the tooltip button from above TextFieldMD3 (lines 31-40). Remove the tooltip content `

` from above (lines 41-44). 3. Create the same `tooltipIcon` element with `onClick`, `onMouseEnter`, `onMouseLeave`, `aria-label={`More info about ${label}`}`. 4. Compute `const tooltipVisible = showTooltip || hoverTooltip`. 5. Pass `helpTextPrefix={tooltipIcon}` to TextFieldMD3. 6. Render tooltip content after TextFieldMD3, conditioned on `tooltipVisible`. IMPORTANT: Preserve existing `aria-label` format exactly as `More info about ${field.label}` (or `${label}` in PasswordField) — existing tests assert this. cd C:/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run --reporter=verbose 2>&1 | tail -30 - Tooltip icon renders inline to the left of helpText below the field (not above the field) - Hovering the tooltip icon shows tooltip text - Clicking the tooltip icon pins tooltip open; clicking again dismisses - Mouse-leaving the icon hides tooltip (unless pinned via click) - All existing tests pass including FieldRenderer aria-label tests - PasswordField has identical fix Task 2: Add tests for tooltip hover behavior and helpTextPrefix rendering src/components/ui/FieldRenderer.test.tsx, src/components/ui/TextFieldMD3.test.tsx - Test: Hovering tooltip button shows tooltip text (fireEvent.mouseEnter on button, then expect tooltipText visible) - Test: Mouse-leaving tooltip button hides tooltip text (fireEvent.mouseLeave, then expect tooltipText not visible) - Test: Clicking tooltip button pins tooltip open, mouseLeave does NOT hide it - Test: TextFieldMD3 renders helpTextPrefix inline with helpText when prop provided - Test: TextFieldMD3 renders helpText normally when helpTextPrefix is not provided **FieldRenderer.test.tsx — Add hover behavior tests:** Add a new describe block `'FieldRenderer - tooltip hover behavior'` with these tests: 1. `'hovering tooltip button shows tooltip text'`: - Render FieldRenderer with `textFieldWithTooltip` (already defined in test file) - Get tooltip button via `screen.getByRole('button', { name: /more info about bucket name/i })` - `fireEvent.mouseEnter(tooltipBtn)` - `expect(screen.getByText('The name of your storage bucket')).toBeDefined()` 2. `'mouse-leaving tooltip button hides tooltip text'`: - Render, mouseEnter, verify visible, then `fireEvent.mouseLeave(tooltipBtn)` - `expect(screen.queryByText('The name of your storage bucket')).toBeNull()` 3. `'clicking tooltip button pins it open through mouseLeave'`: - Render, `fireEvent.click(tooltipBtn)`, `fireEvent.mouseLeave(tooltipBtn)` - `expect(screen.getByText('The name of your storage bucket')).toBeDefined()` (still visible because pinned) 4. `'clicking pinned tooltip button again dismisses it'`: - Render, click (pin), click again (unpin) - `expect(screen.queryByText('The name of your storage bucket')).toBeNull()` Import `fireEvent` from `@testing-library/react` (add to existing import). **TextFieldMD3.test.tsx — Add helpTextPrefix tests:** Add tests in existing file (or create new describe block): 1. `'renders helpTextPrefix inline with helpText'`: - Render TextFieldMD3 with `helpText="Some help"` and `helpTextPrefix={icon}` - `expect(screen.getByTestId('prefix')).toBeDefined()` - `expect(screen.getByText('Some help')).toBeDefined()` 2. `'renders helpText without wrapper issues when helpTextPrefix is undefined'`: - Render TextFieldMD3 with `helpText="Some help"` and no helpTextPrefix - `expect(screen.getByText('Some help')).toBeDefined()` cd C:/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run src/components/ui/FieldRenderer.test.tsx src/components/ui/TextFieldMD3.test.tsx --reporter=verbose 2>&1 | tail -40 - All new tooltip hover tests pass (mouseEnter shows, mouseLeave hides, click pins, click again unpins) - helpTextPrefix rendering test passes - All pre-existing FieldRenderer and TextFieldMD3 tests still pass 1. `npx vitest run --reporter=verbose` — all tests pass (179+ existing + new tooltip tests) 2. Manual spot-check: tooltip icon appears beside helpText below field, not above field 3. Hover behavior: mouseEnter shows tooltip, mouseLeave hides it, click pins it - UAT test 7 passes: tooltip info buttons show tooltip text on hover AND icon is positioned beside helpText below the field - Zero test regressions - Both FieldRenderer (text-branch + select-branch) and PasswordField have hover support - TextFieldMD3 has helpTextPrefix prop for extensibility After completion, create `.planning/phases/09-md3-components/09-05-SUMMARY.md`