# 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: ```tsx 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: ```bash 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: ```bash node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx ``` Expected: PASS for the new first-row region assertion. **Step 5: Commit** ```bash 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: ```tsx 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: ```bash 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: ```bash 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** ```bash 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: ```bash 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: ```bash npm.cmd test npm.cmd run lint npm.cmd run build ``` Expected: - all tests PASS - typecheck PASS - build PASS **Step 5: Commit** ```bash 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" ```