video_translate/docs/plans/2026-03-21-upload-three-card-row.md
2026-03-21 14:04:23 +08:00

4.8 KiB

Upload Three-Card Row Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Refactor the upload page so "Upload source video", "Mode & Workflow", and "Language & Dubbing" appear as three first-row cards on desktop, with "Subtitle Defaults" moved to the next row.

Architecture: Keep the existing upload, trim, subtitle-default, and TTS state behavior intact while changing only the desktop grid composition. The main work is in src/components/UploadScreen.tsx, supported by focused test updates in src/components/UploadScreen.test.tsx. Existing compact header behavior in src/App.tsx can remain unchanged unless minor spacing adjustments are needed after the grid refactor.

Tech Stack: React 19, TypeScript, Tailwind CSS v4 utilities, Vitest, React Testing Library


Task 1: Lock the three-card first row with a failing test

Files:

  • Modify: src/components/UploadScreen.test.tsx
  • Reference: src/components/UploadScreen.tsx

Step 1: Write the failing test

Add a test that describes the new first-row structure:

it('renders upload, mode, and language cards as first-row regions', () => {
  renderUploadScreen();

  expect(screen.getByTestId('upload-dropzone-card')).toBeInTheDocument();
  expect(screen.getByTestId('mode-card')).toBeInTheDocument();
  expect(screen.getByTestId('language-card')).toBeInTheDocument();
  expect(screen.getByTestId('subtitle-defaults-card')).toBeInTheDocument();
});

Step 2: Run test to verify it fails

Run:

node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx

Expected: FAIL because the mode/language/subtitle cards do not expose the new structural markers yet.

Step 3: Write minimal implementation

Add the minimum data-testid hooks needed in src/components/UploadScreen.tsx for the four card regions.

Step 4: Run test to verify it passes

Run:

node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx

Expected: PASS for the new first-row region assertion.

Step 5: Commit

git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx
git commit -m "test: lock upload three-card first row"

Task 2: Refactor the upload workbench grid

Files:

  • Modify: src/components/UploadScreen.tsx
  • Modify: src/components/UploadScreen.test.tsx
  • Reference: src/index.css

Step 1: Write the failing test

Add one more test that preserves the compact language grid after the layout move:

it('keeps the language card controls intact after moving into the first row', () => {
  renderUploadScreen();

  expect(screen.getByTestId('language-card')).toContainElement(screen.getByTestId('tts-language-grid'));
  expect(screen.getByRole('button', { name: 'Generate Translated Video' })).toBeInTheDocument();
});

Step 2: Run test to verify it fails

Run:

node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx

Expected: FAIL until the language card is promoted into its own first-row region.

Step 3: Write minimal implementation

Reshape src/components/UploadScreen.tsx into a desktop-first two-row grid:

  • first row:
    • upload card
    • mode card
    • language card
  • second row:
    • subtitle defaults card

Keep the language card self-contained with:

  • subtitle language context
  • TTS language grid
  • generate button

Keep the subtitle card in the second row with preview and sliders unchanged functionally.

Step 4: Run test to verify it passes

Run:

node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx

Expected: PASS for the new structure and existing interaction tests.

Step 5: Commit

git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx
git commit -m "feat: move language card into first row"

Task 3: Full verification

Files:

  • Modify: src/components/UploadScreen.tsx
  • Modify: src/components/UploadScreen.test.tsx
  • Optionally modify: src/App.tsx

Step 1: Write the failing test

If any final regression gap appears after Task 2, add the smallest targeted test for it before final polish.

Step 2: Run test to verify it fails

Run:

node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx src/App.test.tsx

Expected: FAIL only if a real regression remains.

Step 3: Write minimal implementation

Apply only the final layout polish needed to satisfy the failing regression.

Step 4: Run test to verify it passes

Run:

npm.cmd test
npm.cmd run lint
npm.cmd run build

Expected:

  • all tests PASS
  • typecheck PASS
  • build PASS

Step 5: Commit

git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx src/App.tsx src/App.test.tsx
git commit -m "test: verify upload three-card row layout"