video_translate/docs/plans/2026-03-21-upload-workbench-redesign.md
2026-03-21 12:39:57 +08:00

10 KiB

Upload Workbench Redesign Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Rebuild the upload page into a responsive workbench layout that keeps the settings panel fully accessible while preserving the current upload, trim, subtitle-default, and TTS selection behavior.

Architecture: Keep the existing upload-page workflow and state model, but replace the rigid centered flex layout with a top-aligned page shell and responsive grid. Most of the work lives in src/components/UploadScreen.tsx, with a smaller shell adjustment in src/App.tsx and assertion updates in the upload-page tests. The implementation should stay behavior-compatible and lean on CSS/Tailwind layout changes instead of introducing new product state.

Tech Stack: React 19, TypeScript, Vite, Tailwind CSS v4 utilities, Lucide React icons, Vitest, React Testing Library


Task 1: Lock the redesigned upload-page structure with failing tests

Files:

  • Modify: src/App.test.tsx
  • Modify: src/components/UploadScreen.test.tsx
  • Reference: src/App.tsx
  • Reference: src/components/UploadScreen.tsx

Step 1: Write the failing test

Add assertions that describe the redesigned shell and card structure before implementation:

it('shows the upload workbench header and keeps the language switcher visible', () => {
  render(<App />);

  expect(screen.getByText('Video Translate')).toBeInTheDocument();
  expect(
    screen.getByText('Upload a source video, tune subtitle defaults, and choose dubbing settings before generation.'),
  ).toBeInTheDocument();
  expect(screen.getByLabelText('switch-ui-language-zh')).toBeInTheDocument();
  expect(screen.getByLabelText('switch-ui-language-en')).toBeInTheDocument();
});

it('renders upload, mode, subtitle defaults, and language cards inside the responsive workbench', () => {
  renderUploadScreen();

  expect(screen.getByTestId('upload-workbench')).toBeInTheDocument();
  expect(screen.getByTestId('upload-dropzone-card')).toBeInTheDocument();
  expect(screen.getByTestId('upload-settings-column')).toBeInTheDocument();
  expect(screen.getByRole('heading', { name: 'Mode & Workflow' })).toBeInTheDocument();
  expect(screen.getByRole('heading', { name: 'Subtitle Defaults' })).toBeInTheDocument();
  expect(screen.getByRole('heading', { name: 'Language & Dubbing' })).toBeInTheDocument();
});

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 because the new header copy, section headings, and test ids do not exist yet.

Step 3: Write minimal implementation

Do not redesign everything yet. Add only the smallest missing semantic hooks and copy needed to satisfy the new tests:

  • app-shell heading and intro copy in src/App.tsx
  • stable data-testid markers and section headings in src/components/UploadScreen.tsx

Use copy aligned with the approved design:

<section aria-label="upload-page-intro">
  <p>Video Translate</p>
  <h1>{m.upload.workbenchTitle}</h1>
  <p>{m.upload.workbenchDescription}</p>
</section>

Step 4: Run test to verify it passes

Run:

node ./node_modules/vitest/vitest.mjs run src/App.test.tsx src/components/UploadScreen.test.tsx

Expected: PASS for the new structure assertions, with no unrelated failures in those files.

Step 5: Commit

git add src/App.test.tsx src/components/UploadScreen.test.tsx src/App.tsx src/components/UploadScreen.tsx src/i18n.tsx
git commit -m "test: lock upload workbench shell structure"

Task 2: Rebuild the page shell and header layout

Files:

  • Modify: src/App.tsx
  • Modify: src/i18n.tsx
  • Test: src/App.test.tsx

Step 1: Write the failing test

Extend the app test to assert the header content is grouped into a page shell and remains bilingual:

expect(screen.getByRole('banner')).toBeInTheDocument();
expect(screen.getByRole('heading', { name: 'Upload & prepare' })).toBeInTheDocument();
expect(screen.getByText('Keep subtitle defaults visible and avoid clipped settings panels.')).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 new banner structure and localized hero text are not present yet.

Step 3: Write minimal implementation

Update src/App.tsx and src/i18n.tsx to:

  • wrap the upload page in a proper shell with min-h-screen
  • add a responsive header above the view content
  • move the language switcher into the header
  • add localized upload-page title and description strings for both Chinese and English

Implementation sketch:

<div className="min-h-screen bg-[...gradient...] text-slate-900">
  <div className="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8">
    <header className="mb-8 flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
      <div className="space-y-3">
        <p className="...">{m.app.productName}</p>
        <h1 className="...">{m.upload.workbenchTitle}</h1>
        <p className="...">{m.upload.workbenchDescription}</p>
      </div>
      {languageSwitcher}
    </header>
    {currentView === 'upload' ? <UploadScreen ... /> : <EditorScreen ... />}
  </div>
</div>

Step 4: Run test to verify it passes

Run:

node ./node_modules/vitest/vitest.mjs run src/App.test.tsx

Expected: PASS, showing the new header shell in the upload view and preserving the language toggle behavior.

Step 5: Commit

git add src/App.tsx src/i18n.tsx src/App.test.tsx
git commit -m "feat: add upload page workbench shell"

Task 3: Replace the rigid upload-page flex layout with a responsive workbench grid

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 tests that lock in the redesigned composition while preserving behavior:

it('keeps subtitle preview behavior after the layout redesign', () => {
  renderUploadScreen();

  fireEvent.change(screen.getByLabelText(/subtitle initial size/i), {
    target: { value: '32' },
  });

  expect(screen.getByTestId('upload-subtitle-preview')).toHaveStyle({ fontSize: '32px' });
  expect(screen.getByRole('button', { name: 'Generate Translated Video' })).toBeDisabled();
});

it('keeps the upload interaction wired through the redesigned dropzone card', () => {
  renderUploadScreen();

  expect(screen.getByTestId('upload-dropzone-card')).toContainElement(
    screen.getByLabelText(/upload video file/i),
  );
});

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 current layout does not expose the new workbench structure markers and updated headings yet.

Step 3: Write minimal implementation

Refactor src/components/UploadScreen.tsx to:

  • replace the outer flex ... h-screen items-center shell with a responsive grid container
  • use a wide primary upload card plus a flexible sidebar column
  • remove the fixed w-[400px] sidebar
  • add min-w-0 to shrinkable containers
  • convert the settings area into three distinct cards:
    • mode and workflow
    • subtitle defaults
    • language and dubbing
  • reduce the preview height and tighten card spacing
  • keep the language list internally scrollable
  • keep the primary generation button prominent at the bottom of the settings flow

Representative JSX shape:

<section
  data-testid="upload-workbench"
  className="grid gap-6 xl:grid-cols-[minmax(0,1.65fr)_minmax(320px,420px)]"
>
  <div data-testid="upload-dropzone-card" className="min-w-0 ...">
    ...
  </div>

  <aside data-testid="upload-settings-column" className="min-w-0 space-y-5 xl:sticky xl:top-6">
    <section className="...">
      <h2>{m.upload.modeWorkflowTitle}</h2>
      ...
    </section>
    <section className="...">
      <h2>{m.upload.subtitleDefaults}</h2>
      ...
    </section>
    <section className="...">
      <h2>{m.upload.languageDubbingTitle}</h2>
      ...
    </section>
  </aside>
</section>

If a small amount of shared CSS improves consistency, keep it narrowly scoped in src/index.css:

.app-surface {
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(14px);
}

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 upload-screen interaction tests, including subtitle-preview updates and upload confirmation behavior.

Step 5: Commit

git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx src/index.css src/i18n.tsx
git commit -m "feat: redesign upload page workbench layout"

Task 4: Full verification and cleanup

Files:

  • Modify: src/App.tsx
  • Modify: src/components/UploadScreen.tsx
  • Modify: src/i18n.tsx
  • Modify: src/index.css
  • Test: src/App.test.tsx
  • Test: src/components/UploadScreen.test.tsx

Step 1: Write the failing test

Add one final regression assertion for the bilingual header text to ensure the redesigned shell still switches languages correctly:

fireEvent.click(screen.getByLabelText('switch-ui-language-en'));
expect(screen.getByRole('heading', { name: 'Upload & prepare' })).toBeInTheDocument();
expect(screen.getByText('Upload a source video, tune subtitle defaults, and choose dubbing settings before generation.')).toBeInTheDocument();

Step 2: Run test to verify it fails

Run:

node ./node_modules/vitest/vitest.mjs run src/App.test.tsx

Expected: FAIL until the new localized header copy is fully wired.

Step 3: Write minimal implementation

Complete any remaining polish needed to satisfy the regression coverage:

  • finalize localized header and section labels
  • ensure the upload page stays visually coherent in both locales
  • remove unused classes or stale layout wrappers from the old design

Step 4: Run test to verify it passes

Run:

node ./node_modules/vitest/vitest.mjs run src/App.test.tsx src/components/UploadScreen.test.tsx
npm run lint
npm run build

Expected:

  • targeted tests PASS
  • typecheck PASS
  • production build PASS

Step 5: Commit

git add src/App.tsx src/components/UploadScreen.tsx src/i18n.tsx src/index.css src/App.test.tsx src/components/UploadScreen.test.tsx
git commit -m "test: verify upload workbench redesign"