diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 919ce31..a4facf8 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -66,12 +66,13 @@ Plans: 3. Backend selection cards and output blocks display MD3 elevation with tonal surface tint and consistent shape tokens 4. Step indicator shows numbered circles connected by lines, with checkmarks on completed steps, highlight on current, and muted future steps 5. FieldRenderer produces identical `aria-label` attributes for both text-branch and select-branch inputs -**Plans:** 4/4 plans complete +**Plans:** 5 plans (4 complete + 1 gap closure) Plans: - [x] 09-01-PLAN.md — TextFieldMD3 component, MD3 button constants, DEBT-01 aria-label fix - [x] 09-02-PLAN.md — StepIndicator rebuild with MD3 circles and connectors - [x] 09-03-PLAN.md — Integration: wire TextFieldMD3 + button styles + elevation into all wizard steps - [ ] 09-04-PLAN.md — Gap closure: Replace BackendSelectionStep plain input with TextFieldMD3 +- [ ] 09-05-PLAN.md — Gap closure: Tooltip hover behavior + icon placement beside helpText ### Phase 10: Content & Clarity **Goal**: A first-time visitor understands what Ready2Blob does and what each wizard step expects without external documentation diff --git a/.planning/phases/09-md3-components/09-05-PLAN.md b/.planning/phases/09-md3-components/09-05-PLAN.md new file mode 100644 index 0000000..4dc04fc --- /dev/null +++ b/.planning/phases/09-md3-components/09-05-PLAN.md @@ -0,0 +1,295 @@ +--- +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` +