fix(studio): adapt sidebar thumbnail container to composition aspect ratio#728
Conversation
…ratio Portrait compositions (1080x1920) rendered pillarboxed inside a fixed 80x45px landscape container, wasting space with black bars on both sides. The thumbnail container now derives its dimensions from the composition's stage size: landscape gets 80px wide, portrait gets 45px tall. The preview scale calculation uses matching card dimensions so the iframe fills the container without letterboxing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jrusso1020
left a comment
There was a problem hiding this comment.
Smol PR, smol review. The aspect-ratio math is correct for all three cases in the test plan (landscape, portrait, square). Approving.
What I verified
Logic checks out for the three test-plan cases:
const isPortrait = stageSize.height > stageSize.width;
const cardWidth = isPortrait ? Math.round((45 * stageSize.width) / stageSize.height) : 80;
const cardHeight = isPortrait ? 45 : Math.round((80 * stageSize.height) / stageSize.width);| Composition | isPortrait |
cardWidth |
cardHeight |
|---|---|---|---|
| 1920×1080 (16:9) | false | 80 | round(80 × 1080/1920) = 45 ✓ |
| 1080×1920 (9:16) | true | round(45 × 1080/1920) = 25 | 45 ✓ |
| 1080×1080 (1:1) | false | 80 | round(80 × 1080/1080) = 80 ✓ |
Square goes through the landscape branch (strict > on the isPortrait check), producing 80×80 — which matches the test-plan expectation of "thumbnail should be square." ✓
resolveCompositionPreviewScale gets the matching dimensions so the iframe scale used for the live preview hover state actually fits the new container size, not the old 80×45. Without this, portrait thumbnails would have a misaligned hover iframe. ✓
Tailwind classes replaced cleanly. w-20 h-[45px] (Tailwind 5rem × 45px = 80×45) → inline style={{ width: cardWidth, height: cardHeight }}. The flex-shrink-0 is kept so the thumbnail doesn't shrink when other sidebar content is wide. ✓
Smaller observations (non-blocking)
Extreme portrait edge case: a 9:21 composition (e.g., 1080×2520, vertical Stories format) computes cardWidth = round(45 × 1080/2520) = 19. A 19px-wide thumbnail is technically usable but tight. For typical 9:16 (25px) it's fine — just noting for if anyone runs into ultra-vertical compositions.
stageSize validity is assumed. If stageSize.width === 0 or stageSize.height === 0 (shouldn't happen for a real composition), the math produces Infinity/NaN. CSS would render that as 0. Not a real concern unless there's a code path where stageSize can be zero before reaching this component — worth a defensive Math.max(1, ...) if anyone hits it.
Summary
Tiny, correct, three test cases covered. Approved at 636dbd0e.
— Review by Rames Jusso (pr-review)
miguel-heygen
left a comment
There was a problem hiding this comment.
Clean fix. The aspect ratio math is correct:
- Portrait: height fixed at 45px, width computed proportionally → narrow tall thumbnail
- Landscape: width fixed at 80px, height computed proportionally → standard wide thumbnail
- Square: strict
>sends it to landscape branch → 80×80 which rounds to square via the height calc
The resolveCompositionPreviewScale call correctly receives the new dynamic dimensions so the hover iframe scales to fit. One file, +9/-3. LGTM.
Summary
Portrait compositions (1080x1920) rendered pillarboxed inside a fixed 80x45px landscape container, wasting space with black bars on both sides.
The thumbnail container now derives its dimensions from the composition's stage size: landscape compositions get 80px wide (height from aspect ratio), portrait compositions get 45px tall (width from aspect ratio). The preview scale calculation uses the matching card dimensions so the iframe fills the container without letterboxing.
Test plan
🤖 Generated with Claude Code