docs: add upload three-card row design

This commit is contained in:
Song367 2026-03-21 14:04:23 +08:00
parent fd86f7e10b
commit 7ac7c4b216
2 changed files with 303 additions and 0 deletions

View File

@ -0,0 +1,126 @@
# Upload Three-Card Row Design
**Goal:** Move the "Language & Dubbing" card into the same first-row layout as "Upload source video" and "Mode & Workflow" so the page presents three immediately visible decision areas across the top.
## Context
The compact first-fold redesign reduced vertical overflow, but the page still communicates a two-column mental model:
- a dominant upload card on the left
- a vertical stack of settings cards on the right
Even after compression, the language card still feels like a secondary block that lives below the more obvious controls. The user wants that card elevated into the first visible row so the primary choices are laid out horizontally and read in one scan.
## User-Approved Direction
Use a first-row, three-card layout:
1. Upload source video
2. Mode & Workflow
3. Language & Dubbing
Move "Subtitle Defaults" to the second row beneath those three cards.
## Approaches Considered
### Option A: Three-card top row with subtitle defaults below
Make the page body a two-row grid:
- row 1: upload / mode / language
- row 2: subtitle defaults
**Pros**
- Matches the requested visual model exactly
- Makes the most important choices visible in one scan
- Preserves semantic card boundaries
**Cons**
- Requires a larger grid refactor than simple spacing tweaks
### Option B: Keep two columns and visually pull language upward
Keep the current grid but reorder the right-column cards so language appears above subtitle defaults.
**Pros**
- Smaller code change
**Cons**
- Still reads as one left card plus a stacked sidebar
- Does not satisfy the "three cards in one row" requirement
### Option C: Merge mode and language into one card
Reduce the top row to two cards by combining controls.
**Pros**
- Simple height management
**Cons**
- Weakens scannability
- Mixes unrelated concerns
### Recommendation
Use **Option A**.
## Architecture
### Top-Level Grid
The upload workbench should become a two-row desktop grid with named regions:
- `upload`
- `mode`
- `language`
- `subtitle`
On large desktop widths:
- upload card occupies the wider left column
- mode and language cards sit as two narrower sibling cards to its right
- subtitle defaults spans the width beneath the row or sits below upload and settings depending on the final proportion
The important part is that upload, mode, and language share the same first visual row.
### Card Ownership
Keep card responsibilities clear:
- Upload card: file selection, supporting copy, current mode chip
- Mode card: editing vs simple mode
- Language card: subtitle language context, TTS language choices, primary generate button
- Subtitle card: preview, sliders, reset action
### Responsive Behavior
Desktop-first behavior should prioritize the requested three-card row. At narrower widths, the layout may stack back down, but on the target desktop viewport the first row must visibly contain all three cards.
## Testing Strategy
Add or update tests to cover:
- the language card remains present and visible as a first-class card
- the first-row structure exposes distinct upload, mode, and language regions
- the language grid remains intact after the grid refactor
- subtitle defaults continue to behave the same after moving to a lower row
## Out of Scope
This change does not alter:
- upload logic
- trim flow
- subtitle defaults behavior
- supported language set
- backend request contracts
## Rollout Notes
Success means the user can open the page and immediately see three top-level cards in the first row: upload, mode, and language.

View File

@ -0,0 +1,177 @@
# 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"
```