diff --git a/docs/plans/2026-03-21-subtitle-preview-scale-design.md b/docs/plans/2026-03-21-subtitle-preview-scale-design.md new file mode 100644 index 0000000..7a40589 --- /dev/null +++ b/docs/plans/2026-03-21-subtitle-preview-scale-design.md @@ -0,0 +1,55 @@ +# Subtitle Preview Scale Design + +**Goal:** Make the subtitle sample inside the small preview screen visually proportional by scaling the rendered preview text down, while keeping the real subtitle size values unchanged for export and editing. + +## Context + +The current subtitle defaults card renders the preview text using the raw subtitle font size value. In a compact sample screen, that makes the text appear nearly as tall as the preview display itself, which breaks visual proportion and makes the mock preview feel unrealistic. + +The user approved the "preview scale mapping" direction instead of enlarging the screen or rebuilding the preview as a strict video-canvas simulator. + +## Approved Direction + +- keep the stored subtitle size value unchanged +- keep the slider values unchanged +- keep exported subtitle defaults unchanged +- only scale the preview rendering inside the small sample screen +- make the preview text visually smaller relative to the sample screen + +## Recommended Behavior + +Use a lightweight preview-only mapping: + +- compute a preview font size from the real subtitle size +- apply a clamp so small values do not become unreadable +- keep the label beside the slider showing the real value such as `24px` +- keep upload/export using the real value such as `24` + +This preserves the product meaning of the controls while making the small preview believable. + +## Rendering Rules + +- real subtitle size remains the source of truth in state +- preview font size is a derived value for UI only +- preview outline strength should scale down with the preview text so the stroke does not overpower the sample +- subtitle bottom offset behavior remains unchanged + +## Testing Strategy + +Update upload-screen tests to verify: + +- the preview text no longer renders at the raw `24px` size +- the slider can still change the real font size value +- the preview updates to the mapped display size +- upload confirmation still sends the unmodified real subtitle size + +## Out of Scope + +- changing the export subtitle engine +- changing slider ranges +- redesigning the subtitle defaults card +- introducing full video-canvas simulation + +## Success Criteria + +Success means the sample subtitle looks appropriately smaller than the preview screen, while the UI still communicates and submits the real subtitle size values unchanged. diff --git a/docs/plans/2026-03-21-subtitle-preview-scale.md b/docs/plans/2026-03-21-subtitle-preview-scale.md new file mode 100644 index 0000000..90e4f79 --- /dev/null +++ b/docs/plans/2026-03-21-subtitle-preview-scale.md @@ -0,0 +1,163 @@ +# Subtitle Preview Scale Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Scale subtitle text inside the compact preview screen so it looks proportional, without changing the real subtitle size values used elsewhere in the flow. + +**Architecture:** Keep `subtitleDefaults.fontSize` as the source of truth and derive a preview-only font size in `src/components/UploadScreen.tsx`. Lock the behavior with upload-screen tests that prove the preview is scaled down while upload/export still use the real font size. + +**Tech Stack:** React 19, TypeScript, Tailwind CSS v4 utilities, Vitest, React Testing Library + +--- + +### Task 1: Lock preview-only scaling with a failing test + +**Files:** +- Modify: `src/components/UploadScreen.test.tsx` +- Reference: `src/components/UploadScreen.tsx` + +**Step 1: Write the failing test** + +Update the existing preview test so it expects scaled preview rendering rather than raw font size rendering: + +```tsx +it('scales the subtitle preview while preserving the real subtitle size value', () => { + renderUploadScreen(); + + const sizeSlider = screen.getByLabelText(/subtitle initial size/i); + const positionSlider = screen.getByLabelText(/subtitle initial position/i); + const preview = screen.getByTestId('upload-subtitle-preview'); + + expect(sizeSlider).toHaveValue('24'); + expect(positionSlider).toHaveValue('10'); + expect(preview).toHaveStyle({ fontSize: '12px', bottom: '10%' }); + + fireEvent.change(sizeSlider, { target: { value: '32' } }); + fireEvent.change(positionSlider, { target: { value: '18' } }); + + expect(preview).toHaveStyle({ fontSize: '16px', bottom: '18%' }); +}); +``` + +**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 preview currently renders the raw font size values. + +**Step 3: Write minimal implementation** + +Add a preview-only derived font size and use it for the preview text. + +**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 preview-scaling expectation. + +**Step 5: Commit** + +```bash +git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx +git commit -m "test: lock subtitle preview scaling" +``` + +### Task 2: Keep export behavior unchanged + +**Files:** +- Modify: `src/components/UploadScreen.tsx` +- Reference: `src/components/UploadScreen.test.tsx` + +**Step 1: Write the failing test** + +Use the existing upload-confirmation test as the regression check for preserving the real font size value. + +**Step 2: Run test to verify it fails** + +Run: + +```bash +node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx +``` + +Expected: FAIL only if the implementation accidentally changes uploaded subtitle defaults instead of preview-only rendering. + +**Step 3: Write minimal implementation** + +Ensure only the preview rendering uses the derived font size. Keep: + +- slider state values unchanged +- upload callback values unchanged +- bottom offset behavior unchanged + +**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 both the preview mapping test and the upload-confirmation regression test. + +**Step 5: Commit** + +```bash +git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx +git commit -m "fix: scale subtitle preview text" +``` + +### Task 3: Full verification + +**Files:** +- Modify: `src/components/UploadScreen.tsx` +- Modify: `src/components/UploadScreen.test.tsx` + +**Step 1: Write the failing test** + +If any final regression appears, add the smallest targeted test first. + +**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 smallest visual or logic adjustment needed to restore parity. + +**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 +- lint PASS +- build PASS + +**Step 5: Commit** + +```bash +git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx docs/plans/2026-03-21-subtitle-preview-scale-design.md docs/plans/2026-03-21-subtitle-preview-scale.md +git commit -m "test: verify subtitle preview scaling" +```