Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
273 lines
12 KiB
Markdown
273 lines
12 KiB
Markdown
---
|
|
phase: 09-md3-components
|
|
plan: 03
|
|
type: execute
|
|
wave: 2
|
|
depends_on: ["09-01"]
|
|
files_modified:
|
|
- src/components/ui/FieldRenderer.tsx
|
|
- src/components/ui/PasswordField.tsx
|
|
- src/components/ui/BackendCard.tsx
|
|
- src/components/wizard/OutputBlock.tsx
|
|
- src/components/wizard/BackendSelectionStep.tsx
|
|
- src/components/wizard/RemoteConfigStep.tsx
|
|
- src/components/wizard/DeploymentStep.tsx
|
|
- src/components/wizard/ReviewStep.tsx
|
|
- src/index.css
|
|
autonomous: false
|
|
requirements: [COMP-01, COMP-02, COMP-03]
|
|
|
|
must_haves:
|
|
truths:
|
|
- "All text inputs in the wizard render with floating labels that animate on focus and when the field has content"
|
|
- "Next and Download All buttons use MD3 filled style (rounded-full, bg-primary)"
|
|
- "Back, Copy, and Download buttons use MD3 outlined style (rounded-full, border)"
|
|
- "BackendCard uses rounded-xl shape and shadow elevation"
|
|
- "OutputBlock pre blocks use rounded-xl and subtle shadow"
|
|
- "All existing tests pass with no regressions"
|
|
artifacts:
|
|
- path: "src/components/ui/FieldRenderer.tsx"
|
|
provides: "Text-branch using TextFieldMD3 component"
|
|
contains: "TextFieldMD3"
|
|
- path: "src/components/ui/PasswordField.tsx"
|
|
provides: "Password field using TextFieldMD3 layout"
|
|
contains: "TextFieldMD3"
|
|
- path: "src/components/ui/BackendCard.tsx"
|
|
provides: "MD3 elevation and shape"
|
|
contains: "rounded-xl"
|
|
- path: "src/components/wizard/BackendSelectionStep.tsx"
|
|
provides: "MD3 filled button for Next"
|
|
contains: "MD3_BTN_FILLED"
|
|
key_links:
|
|
- from: "src/components/ui/FieldRenderer.tsx"
|
|
to: "src/components/ui/TextFieldMD3.tsx"
|
|
via: "import and render TextFieldMD3"
|
|
pattern: "import.*TextFieldMD3"
|
|
- from: "src/components/wizard/BackendSelectionStep.tsx"
|
|
to: "src/styles/md3-buttons.ts"
|
|
via: "import button constants"
|
|
pattern: "import.*MD3_BTN"
|
|
- from: "src/components/wizard/ReviewStep.tsx"
|
|
to: "src/styles/md3-buttons.ts"
|
|
via: "import button constants"
|
|
pattern: "import.*MD3_BTN"
|
|
---
|
|
|
|
<objective>
|
|
Wire TextFieldMD3 into FieldRenderer and PasswordField, apply MD3 button styles across all wizard steps, and add MD3 elevation to BackendCard and OutputBlock.
|
|
|
|
Purpose: This is the integration plan that connects the primitives from Plan 01 into the actual wizard UI, completing COMP-01 (floating labels everywhere), COMP-02 (button hierarchy everywhere), and COMP-03 (elevation on cards and code blocks).
|
|
Output: All wizard components updated with MD3 styling.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md
|
|
@C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@.planning/phases/09-md3-components/09-RESEARCH.md
|
|
@.planning/phases/09-md3-components/09-01-SUMMARY.md
|
|
|
|
@src/components/ui/FieldRenderer.tsx
|
|
@src/components/ui/PasswordField.tsx
|
|
@src/components/ui/BackendCard.tsx
|
|
@src/components/wizard/OutputBlock.tsx
|
|
@src/components/wizard/BackendSelectionStep.tsx
|
|
@src/components/wizard/RemoteConfigStep.tsx
|
|
@src/components/wizard/DeploymentStep.tsx
|
|
@src/components/wizard/ReviewStep.tsx
|
|
|
|
<interfaces>
|
|
<!-- TextFieldMD3 and button constants created in Plan 01 -->
|
|
|
|
From src/components/ui/TextFieldMD3.tsx (created in 09-01):
|
|
```typescript
|
|
interface TextFieldMD3Props {
|
|
id: string;
|
|
label: string;
|
|
error?: FieldError;
|
|
registration: UseFormRegisterReturn;
|
|
type?: 'text' | 'password';
|
|
helpText?: string;
|
|
required?: boolean;
|
|
suffix?: React.ReactNode;
|
|
}
|
|
export function TextFieldMD3(props: TextFieldMD3Props): JSX.Element;
|
|
```
|
|
|
|
From src/styles/md3-buttons.ts (created in 09-01):
|
|
```typescript
|
|
export const MD3_BTN_FILLED: string; // filled primary action
|
|
export const MD3_BTN_OUTLINED: string; // outlined secondary action
|
|
export const MD3_BTN_TEXT: string; // text tertiary action
|
|
```
|
|
</interfaces>
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Integrate TextFieldMD3 into FieldRenderer and PasswordField</name>
|
|
<files>src/components/ui/FieldRenderer.tsx, src/components/ui/PasswordField.tsx</files>
|
|
<action>
|
|
**FieldRenderer.tsx — text branch (default, lines 82-119):**
|
|
Replace the entire text-branch return block with a `<TextFieldMD3>` render. Import TextFieldMD3 at top. The text branch currently renders label + input + helpText + error manually. Replace with:
|
|
```tsx
|
|
return (
|
|
<div className="flex flex-col gap-1">
|
|
{field.tooltipText && /* keep tooltip button + tooltip display exactly as-is */}
|
|
<TextFieldMD3
|
|
id={field.key}
|
|
label={field.label}
|
|
error={error}
|
|
registration={register(field.key)}
|
|
helpText={field.helpText}
|
|
required={field.required}
|
|
/>
|
|
</div>
|
|
);
|
|
```
|
|
CRITICAL: The tooltip button (lines 88-99) must remain OUTSIDE TextFieldMD3, rendered above it. TextFieldMD3 handles the label, input, helpText, and error display. The tooltip is a separate concern that stays in FieldRenderer.
|
|
|
|
Actually, re-examining the layout: the current text branch has tooltip button inline with label. Since TextFieldMD3 includes its own label (floating), the tooltip must be rendered separately. Place the tooltip button + tooltip content ABOVE the TextFieldMD3 component in the flex column. This preserves existing tooltip behavior.
|
|
|
|
Keep the select branch (lines 40-79) UNCHANGED — select fields do NOT get floating labels.
|
|
|
|
**PasswordField.tsx:**
|
|
Replace the manual label + input layout with TextFieldMD3, passing the show/hide toggle as `suffix`:
|
|
```tsx
|
|
import { TextFieldMD3 } from './TextFieldMD3';
|
|
|
|
export function PasswordField({ id, label, error, registration, helpText, tooltipText }: PasswordFieldProps) {
|
|
const [show, setShow] = useState(false);
|
|
const [showTooltip, setShowTooltip] = useState(false);
|
|
|
|
const toggleButton = (
|
|
<button type="button" onClick={() => setShow(v => !v)}
|
|
aria-label={show ? 'Hide' : 'Show'}
|
|
className="text-on-surface-container/50 hover:text-on-surface-container text-sm">
|
|
{show ? 'Hide' : 'Show'}
|
|
</button>
|
|
);
|
|
|
|
return (
|
|
<div className="flex flex-col gap-1">
|
|
{tooltipText && (
|
|
<button type="button" onClick={() => setShowTooltip(v => !v)}
|
|
aria-label={`More info about ${label}`}
|
|
className="text-primary hover:text-primary text-xs leading-none self-start">
|
|
ⓘ
|
|
</button>
|
|
)}
|
|
{tooltipText && showTooltip && (
|
|
<p className="text-xs text-primary bg-primary/10 border border-primary/30 rounded px-2 py-1.5">
|
|
{tooltipText}
|
|
</p>
|
|
)}
|
|
<TextFieldMD3
|
|
id={id}
|
|
label={label}
|
|
error={error}
|
|
registration={registration}
|
|
type={show ? 'text' : 'password'}
|
|
helpText={helpText}
|
|
suffix={toggleButton}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
Remove the `placeholder` prop from PasswordFieldProps interface since TextFieldMD3 uses `placeholder=" "` internally.
|
|
|
|
Run full test suite after — ALL `getByLabelText` queries must still work because TextFieldMD3 preserves htmlFor/id pairing.
|
|
</action>
|
|
<verify>
|
|
<automated>npx vitest run --reporter=dot</automated>
|
|
</verify>
|
|
<done>FieldRenderer text-branch renders TextFieldMD3 with floating label. PasswordField uses TextFieldMD3 with suffix for show/hide toggle. All existing tests pass (getByLabelText queries work). No regressions.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Apply MD3 button styles and elevation across all wizard steps</name>
|
|
<files>src/components/wizard/BackendSelectionStep.tsx, src/components/wizard/RemoteConfigStep.tsx, src/components/wizard/DeploymentStep.tsx, src/components/wizard/ReviewStep.tsx, src/components/wizard/OutputBlock.tsx, src/components/ui/BackendCard.tsx, src/index.css</files>
|
|
<action>
|
|
**Button styling (COMP-02):** Import `{ MD3_BTN_FILLED, MD3_BTN_OUTLINED }` from `../../styles/md3-buttons` in each wizard step file. Apply className replacements:
|
|
|
|
BackendSelectionStep.tsx: "Next" button gets `className={MD3_BTN_FILLED}`. No Back button here.
|
|
RemoteConfigStep.tsx: "Back" button gets `className={MD3_BTN_OUTLINED}`, "Next" (submit) button gets `className={MD3_BTN_FILLED}`.
|
|
DeploymentStep.tsx: "Back" button gets `className={MD3_BTN_OUTLINED}`, "Next" button gets `className={MD3_BTN_FILLED}`.
|
|
ReviewStep.tsx: "Back" button gets `className={MD3_BTN_OUTLINED}`, "Download All (ZIP)" button gets `className={MD3_BTN_FILLED}`.
|
|
OutputBlock.tsx: "Copy" button gets `className={MD3_BTN_OUTLINED + ' text-xs !px-3 !py-1'}` (keep smaller size). "Download" button gets same. Import from `../../styles/md3-buttons`. Note: OutputBlock buttons are small utility buttons — keep `text-xs` and reduce padding with overrides. Alternatively, create a size-reduced variant inline: `className={\`\${MD3_BTN_OUTLINED} !text-xs !px-3 !py-1.5\`}`.
|
|
|
|
CRITICAL: Do NOT change button text content — only className. Tests use `getByRole('button', { name: /next/i })` etc.
|
|
|
|
**BackendCard elevation (COMP-03):**
|
|
Update BackendCard.tsx className:
|
|
- Change `rounded-lg` to `rounded-xl` (MD3 medium shape, 12px)
|
|
- Add `shadow hover:shadow-md` to unselected state
|
|
- Selected state: add `shadow-md`
|
|
- Add `transition-all` (already present — keep)
|
|
|
|
**OutputBlock elevation (COMP-03):**
|
|
Update OutputBlock.tsx `<pre>` className:
|
|
- Change `rounded` to `rounded-xl`
|
|
- Add `shadow-sm`
|
|
|
|
**Optional: Add elevation shadow token to index.css:**
|
|
If standard Tailwind `shadow` is insufficient, add to `@theme` block:
|
|
```css
|
|
--shadow-elevation-1: 0 1px 4px 0 rgb(0 0 0 / 0.37);
|
|
```
|
|
Only add this if the default `shadow` utility doesn't provide enough visual lift. Use your judgment.
|
|
|
|
Run full test suite after all changes.
|
|
</action>
|
|
<verify>
|
|
<automated>npx vitest run --reporter=dot</automated>
|
|
</verify>
|
|
<done>All Next/Download buttons use MD3 filled (rounded-full, bg-primary). All Back/Copy buttons use MD3 outlined (rounded-full, border). BackendCard has rounded-xl and shadow. OutputBlock pre has rounded-xl and shadow-sm. All tests pass.</done>
|
|
</task>
|
|
|
|
<task type="checkpoint:human-verify" gate="blocking">
|
|
<name>Task 3: Visual verification of complete MD3 component set</name>
|
|
<what-built>Complete MD3 component migration: floating label text fields, MD3 button hierarchy (filled/outlined), card elevation, and rebuilt step indicator</what-built>
|
|
<how-to-verify>
|
|
1. Run `npm run dev` and open http://localhost:5173
|
|
2. **Step Indicator:** Verify numbered circles with connector lines at top. Step 1 should be highlighted, future steps muted.
|
|
3. **Backend Selection:** Click a backend card — verify rounded corners (rounded-xl) and shadow elevation. Verify "Next" button is pill-shaped (rounded-full) with primary fill color.
|
|
4. **Remote Config:** Verify text inputs have floating labels that animate up on focus and stay floated when field has value. Verify "Back" button is pill-shaped outlined, "Next" is pill-shaped filled.
|
|
5. **Password fields:** Verify floating label works with show/hide toggle button visible on right side.
|
|
6. **Deployment Step:** Verify Back/Next button styles match MD3 hierarchy.
|
|
7. **Review Step:** Verify "Back" is outlined, "Download All" is filled. Verify OutputBlock code areas have rounded corners and subtle shadow. Verify Copy/Download buttons are outlined style.
|
|
8. **Navigate back** to step 1 — verify step indicator shows checkmark on completed step, and the step is clickable.
|
|
9. **Toggle dark mode** — verify all new components look correct in dark theme (no hardcoded colors, shadows work).
|
|
</how-to-verify>
|
|
<resume-signal>Type "approved" or describe issues</resume-signal>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
- `npx vitest run` — full suite passes (166+ tests, zero regressions)
|
|
- All text inputs render floating labels
|
|
- Buttons follow MD3 filled/outlined/text hierarchy
|
|
- Cards and code blocks have MD3 elevation
|
|
- Dark mode renders correctly
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- COMP-01: All text inputs (FieldRenderer text-branch + PasswordField) render as MD3 outlined fields with floating labels
|
|
- COMP-02: Buttons across all wizard steps follow filled/outlined/text hierarchy
|
|
- COMP-03: BackendCard has rounded-xl + shadow, OutputBlock pre has rounded-xl + shadow-sm
|
|
- Zero test regressions
|
|
- User visually approves the complete MD3 component set
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/09-md3-components/09-03-SUMMARY.md`
|
|
</output>
|