docs: add upload three-card row design
This commit is contained in:
parent
fd86f7e10b
commit
7ac7c4b216
126
docs/plans/2026-03-21-upload-three-card-row-design.md
Normal file
126
docs/plans/2026-03-21-upload-three-card-row-design.md
Normal 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.
|
||||
177
docs/plans/2026-03-21-upload-three-card-row.md
Normal file
177
docs/plans/2026-03-21-upload-three-card-row.md
Normal 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"
|
||||
```
|
||||
Loading…
x
Reference in New Issue
Block a user