7.6 KiB
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:
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:
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:
node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx
Expected: PASS for the new compact-language assertion.
Step 5: Commit
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:
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:
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:
workbenchDescription: 'Everything you need to start translation is visible right away.'
Step 4: Run test to verify it passes
Run:
node ./node_modules/vitest/vitest.mjs run src/App.test.tsx
Expected: PASS for the compact-header assertion.
Step 5: Commit
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:
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:
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:
<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:
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
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:
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:
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/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"