docs(10-content-clarity): create phase plan
3 plans in 1 wave covering UX-01 through UX-04: intro section, remote name preview, step descriptions, and credential help text. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
---
|
||||
phase: 10-content-clarity
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- src/components/ui/RemoteNamePreview.tsx
|
||||
- src/components/ui/RemoteNamePreview.test.tsx
|
||||
- src/components/wizard/BackendSelectionStep.tsx
|
||||
- src/components/wizard/BackendSelectionStep.test.tsx
|
||||
autonomous: true
|
||||
requirements:
|
||||
- UX-02
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Remote name field displays help text explaining what the name is and giving examples"
|
||||
- "A live config preview below the field updates as user types, showing [remote-name] syntax"
|
||||
- "When field is empty, preview shows grayed-out [my-remote] placeholder with guidance text"
|
||||
- "When field has content, preview shows [typed-value] in monospace code style"
|
||||
artifacts:
|
||||
- path: "src/components/ui/RemoteNamePreview.tsx"
|
||||
provides: "Stateless display component for rclone config preview"
|
||||
exports: ["RemoteNamePreview"]
|
||||
min_lines: 15
|
||||
- path: "src/components/ui/RemoteNamePreview.test.tsx"
|
||||
provides: "Tests for empty-state and value-state rendering"
|
||||
contains: "RemoteNamePreview"
|
||||
- path: "src/components/wizard/BackendSelectionStep.tsx"
|
||||
provides: "watch('name') integration and RemoteNamePreview placement"
|
||||
contains: "RemoteNamePreview"
|
||||
key_links:
|
||||
- from: "src/components/wizard/BackendSelectionStep.tsx"
|
||||
to: "src/components/ui/RemoteNamePreview.tsx"
|
||||
via: "watch('name') value passed as prop"
|
||||
pattern: "watch\\('name'\\)"
|
||||
- from: "src/components/wizard/BackendSelectionStep.tsx"
|
||||
to: "TextFieldMD3"
|
||||
via: "helpText prop on remote name field"
|
||||
pattern: "helpText="
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add a live rclone config preview below the remote name field and enrich the field with help text.
|
||||
|
||||
Purpose: Users immediately see how their chosen name will appear in the generated rclone.conf, reducing confusion about naming conventions.
|
||||
Output: RemoteNamePreview component, integrated into BackendSelectionStep with watch(), helpText on remote name field.
|
||||
</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/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/10-content-clarity/10-CONTEXT.md
|
||||
@.planning/phases/10-content-clarity/10-RESEARCH.md
|
||||
|
||||
<interfaces>
|
||||
<!-- Key contracts the executor needs -->
|
||||
|
||||
From src/components/wizard/BackendSelectionStep.tsx (existing useForm destructure):
|
||||
```tsx
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm<RemoteNameFormValues>({
|
||||
resolver: zodResolver(remoteNameSchema),
|
||||
mode: 'onSubmit',
|
||||
reValidateMode: 'onChange',
|
||||
defaultValues: { name: state.remote.name },
|
||||
});
|
||||
```
|
||||
Add `watch` to the destructure: `const { register, handleSubmit, watch, formState: { errors } } = useForm<...>(...)`
|
||||
Then: `const remoteName = watch('name');`
|
||||
|
||||
From src/components/ui/TextFieldMD3.tsx (props interface — supports helpText):
|
||||
```tsx
|
||||
// TextFieldMD3 accepts helpText prop — renders as small text below input
|
||||
// CRITICAL: Do NOT pass a visible placeholder prop. TextFieldMD3 uses placeholder=" "
|
||||
// (single space) for the floating label CSS trick. The "e.g. my-backup" example
|
||||
// must be conveyed through helpText, NOT native placeholder.
|
||||
```
|
||||
|
||||
MD3 token classes for preview block (same as ReviewStep OutputBlock):
|
||||
- `bg-surface-variant` — tinted background
|
||||
- `text-on-surface-variant` — readable text on that background
|
||||
- `font-mono` — code appearance
|
||||
|
||||
From BackendSelectionStep.test.tsx (selector pattern):
|
||||
```tsx
|
||||
// Uses screen.getByRole('textbox') — single textbox assertion
|
||||
// RemoteNamePreview MUST NOT render any form controls (input, textarea, contenteditable)
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Create RemoteNamePreview component with tests</name>
|
||||
<files>src/components/ui/RemoteNamePreview.tsx, src/components/ui/RemoteNamePreview.test.tsx</files>
|
||||
<behavior>
|
||||
- When value is empty string or whitespace-only, renders "[my-remote]" as placeholder with "Type a name to see how it appears in your config" guidance text
|
||||
- When value is "my-backup", renders "[my-backup]" in monospace style
|
||||
- When value is "azure-prod", renders "[azure-prod]"
|
||||
- Component renders only display elements (div, span) — never form controls
|
||||
</behavior>
|
||||
<action>
|
||||
Create `RemoteNamePreview` as a stateless functional component accepting `{ value: string }`.
|
||||
|
||||
Empty state: Show grayed-out `[my-remote]` text with a guidance message "Type a name to see how it appears in your config" below it. Use `text-on-surface-variant/50` for the placeholder and `text-on-surface-variant/40` for the guidance.
|
||||
|
||||
Value state: Show `[{value}]` in `text-on-surface-variant` color.
|
||||
|
||||
Container styling: `mt-2 rounded-md bg-surface-variant px-3 py-2 text-xs font-mono`
|
||||
|
||||
Write tests FIRST (RED), then implement (GREEN). Test file uses `@testing-library/react` render + screen assertions.
|
||||
|
||||
CRITICAL: RemoteNamePreview must render ONLY div/span elements. No input, textarea, or contenteditable — this would break BackendSelectionStep.test.tsx's `getByRole('textbox')` single-match assertion.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>npx vitest run src/components/ui/RemoteNamePreview.test.tsx</automated>
|
||||
</verify>
|
||||
<done>RemoteNamePreview renders empty-state placeholder when value is empty, and [value] when value is provided. All tests pass.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Integrate RemoteNamePreview and helpText into BackendSelectionStep</name>
|
||||
<files>src/components/wizard/BackendSelectionStep.tsx, src/components/wizard/BackendSelectionStep.test.tsx</files>
|
||||
<action>
|
||||
In BackendSelectionStep.tsx:
|
||||
1. Add `watch` to the useForm destructure
|
||||
2. Add `const remoteName = watch('name');` after the useForm call
|
||||
3. Add `helpText` prop to the remote name TextFieldMD3: `"This becomes the section header [name] in your rclone.conf. Example: azure-prod, backup-s3. Letters, numbers, dashes, underscores only."` (per user decision)
|
||||
4. Import and render `<RemoteNamePreview value={remoteName} />` directly below the TextFieldMD3
|
||||
|
||||
In BackendSelectionStep.test.tsx:
|
||||
Add a test case that verifies the live preview updates:
|
||||
1. Render BackendSelectionStep
|
||||
2. Assert that the empty-state placeholder text is visible (e.g., "[my-remote]")
|
||||
3. Type "test-remote" into the textbox
|
||||
4. Assert that "[test-remote]" is visible in the DOM
|
||||
|
||||
IMPORTANT: Do NOT add a visible `placeholder` prop to TextFieldMD3. The floating label CSS trick depends on `placeholder=" "`. The "e.g. my-backup" example is conveyed via helpText.
|
||||
IMPORTANT: Do NOT use `useWatch` — plain `watch('name')` from useForm is correct here.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>npx vitest run src/components/wizard/BackendSelectionStep.test.tsx</automated>
|
||||
</verify>
|
||||
<done>Remote name field shows helpText. RemoteNamePreview renders below the field and updates live as user types. All BackendSelectionStep tests pass.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `npx vitest run src/components/ui/RemoteNamePreview.test.tsx` — preview component tests pass
|
||||
2. `npx vitest run src/components/wizard/BackendSelectionStep.test.tsx` — integration tests pass
|
||||
3. `npx vitest run` — full suite green
|
||||
4. Empty field shows [my-remote] placeholder with guidance text
|
||||
5. Typing a name shows [typed-name] in real-time
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- RemoteNamePreview component exists and is tested
|
||||
- BackendSelectionStep shows helpText on remote name field
|
||||
- Live preview below field updates as user types
|
||||
- Empty state shows grayed placeholder with guidance
|
||||
- No existing tests broken (especially getByRole('textbox') single match)
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/10-content-clarity/10-02-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user