docs: add first-fold upload layout design

This commit is contained in:
Song367 2026-03-21 13:56:16 +08:00
parent 5234f5b5db
commit 5c750ae34f
2 changed files with 452 additions and 0 deletions

View File

@ -0,0 +1,189 @@
# Upload First-Fold Layout Design
**Goal:** Make the upload page fit the primary workflow into the first visible desktop viewport so users can immediately see upload, mode selection, subtitle defaults, and dubbing choices without needing to scroll to discover more options.
## Context
The current upload workbench fixed the horizontal clipping problem, but the vertical footprint is still too tall. The page header, large upload surface, generous card spacing, subtitle preview height, and long TTS list combine to push the language card below the fold on common desktop windows.
That creates a discovery problem: users may not realize the page continues below, so important settings can be missed entirely even though the layout is technically responsive.
## User-Approved Direction
The approved direction is:
- keep everything on a single page
- prioritize first-fold visibility on common desktop screens
- avoid making users scroll to discover key settings
- compress the current layout rather than changing the product flow
## Approaches Considered
### Option A: Compact first-fold workbench
Reduce vertical whitespace, shorten the upload card, tighten the right-side cards, and replace the tall language list with a compact always-visible button grid.
**Pros**
- Preserves the current workflow and layout logic
- Directly addresses the "hidden options below the fold" problem
- Keeps all major choices visible at once
**Cons**
- Requires denser spacing and more careful visual balance
### Option B: Merge the settings cards
Combine multiple settings sections into one large card to reduce stack height.
**Pros**
- Fewer visual blocks
- Lower total vertical gap
**Cons**
- Weakens hierarchy
- Makes scanning and editing harder
### Option C: Move one settings section into the upload card
Embed mode selection or language selection into the left upload card.
**Pros**
- Reduces right-column height quickly
**Cons**
- Creates mixed responsibilities inside the upload card
- Makes the composition feel less structured
### Recommendation
Use **Option A**. It preserves a clear workbench layout while making all key actions visible in the first fold.
## Architecture
### Header Compression
The upload-page header should become a slimmer top strip:
- smaller vertical padding
- smaller title scale
- reduced bottom margin
- language switcher remains visible but no longer consumes hero-card space
The header still provides context, but it should stop competing with the main workspace for height.
### Upload Card Compression
The left upload card should remain the primary visual anchor, but it no longer needs a tall poster-like dropzone.
Adjustments:
- reduce top summary spacing
- shorten the dropzone height substantially
- tighten the button and support-copy spacing
- keep mode summary compact
The upload action should still read as primary, just not oversized.
### Right Column Compression
Keep the three semantic cards:
1. mode and workflow
2. subtitle defaults
3. language and dubbing
But each card should be tightened:
- smaller paddings
- smaller inter-card gaps
- smaller preview panel
- less decorative empty space
### TTS Language Visibility
The biggest vertical cost comes from the current alphabet-tab + scrolling list treatment. Replace it with an always-visible compact grid of language buttons.
For the current supported languages, a compact grid is sufficient and preferable because:
- all options are visible immediately
- there is no hidden overflow area
- the user does not need to infer that more settings exist below
This is a visibility optimization, not a data-model change.
## Layout Rules
### Desktop-First Height Budget
Target the upload page body to sit comfortably within the first fold on common desktop heights. The implementation may use:
- tighter shell spacing
- a more compact upload-card min height
- reduced card gaps
- right-column sections that size to content without scroll regions
### No Discovery Scroll for Core Options
Core settings that must be visible without scrolling:
- upload entry point
- mode selection
- subtitle default preview and sliders
- subtitle language context
- all supported TTS language options
- primary "Generate Translated Video" button
### Fallback Behavior
If the viewport is unusually short, the page may still scroll slightly. But normal desktop usage should not require scrolling to discover additional settings.
## Interaction Details
### Mode Selection
Mode options should become denser selection blocks. Keep both options visible at once, but reduce their height and spacing.
### Subtitle Defaults
Keep:
- reset action
- preview
- position slider
- size slider
Reduce the preview height enough to preserve usefulness while reclaiming space.
### TTS Languages
Present the current supported languages as a compact grid, using the existing localized labels and current selection styling. Remove the alphabet tabs and long per-letter sections because they optimize for a larger catalog than this page currently has.
## Testing Strategy
Add or update tests to cover:
- the compact upload layout still renders all major cards
- all TTS language buttons remain visible without the old tabbed list structure
- existing subtitle default interactions still work
- upload behavior and trim flow are unchanged
Manual verification should focus on a common desktop viewport to confirm that the bottom card no longer drops below the fold.
## Out of Scope
This revision does not:
- change the upload workflow
- add or remove supported languages
- redesign the editor screen
- change backend contracts
## Rollout Notes
Success means a user can land on the upload page and immediately understand every major choice without needing to notice or guess that the page continues below the fold.

View File

@ -0,0 +1,263 @@
# Upload First-Fold Layout Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Compress the upload workbench so the complete upload workflow remains visible in the first desktop viewport without forcing users to scroll to discover mode, subtitle, and dubbing options.
**Architecture:** Keep the existing upload screen state and action flow intact, but reduce the upload page's vertical footprint. Most of the work stays inside `src/App.tsx` and `src/components/UploadScreen.tsx`, with supporting text updates in `src/i18n.tsx`, one small surface helper in `src/index.css`, and test updates in the existing app/upload test files. The tall TTS list will be replaced with a compact grid so all supported language choices are immediately visible.
**Tech Stack:** React 19, TypeScript, Tailwind CSS v4 utilities, Vitest, React Testing Library
---
### Task 1: Lock the compact first-fold language layout with failing tests
**Files:**
- Modify: `src/components/UploadScreen.test.tsx`
- Reference: `src/components/UploadScreen.tsx`
**Step 1: Write the failing test**
Add a test that describes the compact language section and rejects the old tabbed list structure:
```tsx
it('shows all supported tts languages in a compact always-visible grid', () => {
renderUploadScreen();
expect(screen.getByTestId('tts-language-grid')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Chinese' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Cantonese' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'English' })).toBeInTheDocument();
expect(screen.queryByText('ABC')).not.toBeInTheDocument();
expect(screen.queryByText('GHI')).not.toBeInTheDocument();
expect(screen.queryByText('DEF')).not.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 upload page still renders the alphabet tabs and has no compact grid marker.
**Step 3: Write minimal implementation**
Update `src/components/UploadScreen.tsx` just enough to:
- remove the old alphabet tabs
- expose a compact language grid container with `data-testid="tts-language-grid"`
- keep the existing language buttons and selection behavior
**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 compact-language assertion.
**Step 5: Commit**
```bash
git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx
git commit -m "test: lock compact tts language layout"
```
### Task 2: Compress the upload page shell and card heights
**Files:**
- Modify: `src/App.tsx`
- Modify: `src/components/UploadScreen.tsx`
- Modify: `src/i18n.tsx`
- Modify: `src/index.css`
- Test: `src/App.test.tsx`
**Step 1: Write the failing test**
Add an app-level test that captures the compact first-fold shell:
```tsx
it('renders the upload shell with compact first-fold copy', () => {
render(<App />);
fireEvent.click(screen.getByLabelText('switch-ui-language-en'));
expect(screen.getByRole('heading', { name: 'Upload & prepare' })).toBeInTheDocument();
expect(screen.getByText('Everything you need to start translation is visible right away.')).toBeInTheDocument();
});
```
**Step 2: Run test to verify it fails**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/App.test.tsx
```
Expected: FAIL because the compact shell copy does not exist yet.
**Step 3: Write minimal implementation**
Update the upload shell and localized copy to reduce the first-fold height budget:
- shrink upload-header padding and margins
- reduce title and description footprint
- tighten workbench spacing
- keep the language switcher visible
Localized copy example:
```tsx
workbenchDescription: 'Everything you need to start translation is visible right away.'
```
**Step 4: Run test to verify it passes**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/App.test.tsx
```
Expected: PASS for the compact-header assertion.
**Step 5: Commit**
```bash
git add src/App.tsx src/App.test.tsx src/i18n.tsx src/index.css
git commit -m "feat: compress upload shell for first-fold visibility"
```
### Task 3: Tighten the upload card and settings cards to fit the first fold
**Files:**
- Modify: `src/components/UploadScreen.tsx`
- Modify: `src/components/UploadScreen.test.tsx`
- Modify: `src/index.css`
- Reference: `src/types.ts`
**Step 1: Write the failing test**
Add targeted structure checks for the compact card composition:
```tsx
it('keeps the compact upload controls and primary action visible together', () => {
renderUploadScreen();
expect(screen.getByTestId('upload-dropzone-card')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Upload Video' })).toBeInTheDocument();
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 compact layout and new language grid are fully in place.
**Step 3: Write minimal implementation**
Refactor `src/components/UploadScreen.tsx` to reclaim vertical space:
- reduce upload-card header spacing
- shorten the dropzone min height
- reduce top and bottom padding on all cards
- tighten card gaps
- shrink subtitle preview height
- compress mode buttons
- render the TTS language options in a multi-column grid instead of a scrolling letter list
- keep the generate button at the bottom of the visible settings stack
Representative shape:
```tsx
<aside className="grid gap-4">
<section className="...compact-mode-card..." />
<section className="...compact-subtitle-card..." />
<section className="...compact-language-card...">
<div data-testid="tts-language-grid" className="grid grid-cols-2 gap-2">
...
</div>
</section>
</aside>
```
**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 compact-card and compact-language assertions while preserving existing upload behavior tests.
**Step 5: Commit**
```bash
git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx src/index.css src/i18n.tsx
git commit -m "feat: fit upload workbench into first fold"
```
### Task 4: Full verification
**Files:**
- Modify: `src/App.tsx`
- Modify: `src/App.test.tsx`
- Modify: `src/components/UploadScreen.tsx`
- Modify: `src/components/UploadScreen.test.tsx`
- Modify: `src/i18n.tsx`
- Modify: `src/index.css`
**Step 1: Write the failing test**
If any final localized copy or structure assertions remain missing after Tasks 1-3, add the smallest regression test needed before the last polish.
**Step 2: Run test to verify it fails**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/App.test.tsx src/components/UploadScreen.test.tsx
```
Expected: FAIL only if the final regression gap is real.
**Step 3: Write minimal implementation**
Apply only the last polish needed to satisfy the failing regression test, without broadening scope.
**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/App.tsx src/App.test.tsx src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx src/i18n.tsx src/index.css
git commit -m "test: verify first-fold upload layout"
```