From 61126991330cd51afed9570b39b0458f4c785692 Mon Sep 17 00:00:00 2001 From: Song367 <601337784@qq.com> Date: Sat, 21 Mar 2026 12:39:57 +0800 Subject: [PATCH] docs: add upload workbench redesign plan --- .../2026-03-21-upload-workbench-redesign.md | 336 ++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 docs/plans/2026-03-21-upload-workbench-redesign.md diff --git a/docs/plans/2026-03-21-upload-workbench-redesign.md b/docs/plans/2026-03-21-upload-workbench-redesign.md new file mode 100644 index 0000000..bec3384 --- /dev/null +++ b/docs/plans/2026-03-21-upload-workbench-redesign.md @@ -0,0 +1,336 @@ +# 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: + +```tsx +it('shows the upload workbench header and keeps the language switcher visible', () => { + render(); + + 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: + +```bash +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: + +```tsx +
+

Video Translate

+

{m.upload.workbenchTitle}

+

{m.upload.workbenchDescription}

+
+``` + +**Step 4: Run test to verify it passes** + +Run: + +```bash +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** + +```bash +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: + +```tsx +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: + +```bash +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: + +```tsx +
+
+
+
+

{m.app.productName}

+

{m.upload.workbenchTitle}

+

{m.upload.workbenchDescription}

+
+ {languageSwitcher} +
+ {currentView === 'upload' ? : } +
+
+``` + +**Step 4: Run test to verify it passes** + +Run: + +```bash +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** + +```bash +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: + +```tsx +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: + +```bash +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: + +```tsx +
+
+ ... +
+ + +
+``` + +If a small amount of shared CSS improves consistency, keep it narrowly scoped in `src/index.css`: + +```css +.app-surface { + background: rgba(255, 255, 255, 0.86); + backdrop-filter: blur(14px); +} +``` + +**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 upload-screen interaction tests, including subtitle-preview updates and upload confirmation behavior. + +**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: 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: + +```tsx +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: + +```bash +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: + +```bash +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** + +```bash +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" +```