refactor(studio): simplify preview workspace layout#2756
Conversation
There was a problem hiding this comment.
Pull request overview
Refactors Studio’s preview/workspace chrome to reduce duplicated transport/seek UI and improve default panel ergonomics, while persisting user panel width adjustments via UI preferences.
Changes:
- Persist left/right panel widths in
studioUiPreferencesand initialize default widths responsively from viewport size. - Simplify preview transport controls by removing the preview seekbar + drag helper, and adjusting control layout/styling.
- Adjust default UI ergonomics (Design tab opens by default; increased default timeline height; minor panel styling tweaks).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/studio/src/utils/studioUiPreferences.ts | Adds stored preference fields for leftWidth / rightWidth and reads them from storage. |
| packages/studio/src/utils/studioUiPreferences.test.ts | Extends preference merge/malformed-value tests to cover persisted panel widths. |
| packages/studio/src/player/components/useSeekBarDrag.ts | Removes now-dead seekbar drag helper (preview seekbar removed). |
| packages/studio/src/player/components/SpeedMenu.tsx | Updates speed menu button styling to match simplified transport chrome. |
| packages/studio/src/player/components/ShortcutsPanel.tsx | Updates shortcuts toggle button styling to match simplified transport chrome. |
| packages/studio/src/player/components/PlayerControls.tsx | Removes preview seekbar UI; reworks transport layout; keeps time display updated via liveTime. |
| packages/studio/src/player/components/PlayerControls.test.ts | Deletes tests tied to the removed resolveSeekPercent/seekbar logic. |
| packages/studio/src/hooks/usePanelLayout.ts | Computes initial panel widths from viewport + preferences; defaults right panel to open + Design tab; persists widths on resize end. |
| packages/studio/src/hooks/usePanelLayout.test.ts | Adds test coverage for viewport-scaled default widths and updated right-panel defaults. |
| packages/studio/src/components/StudioRightPanel.tsx | Tweaks right panel background to match updated chrome. |
| packages/studio/src/components/nle/NLEContext.tsx | Increases default timeline height to give the timeline more space by default. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
miguel-heygen
left a comment
There was a problem hiding this comment.
Reviewed exact head 4178332c8c29c100133c3388695ce90a0aeb3278.
The layout refactor is a real simplification: it removes the duplicate seekbar/drag implementation, retains global keyboard seeking, and the remaining panel composition is easier to follow. I found no blocking behavior loss.
Important follow-up
packages/studio/src/components/StudioLeftSidebar.tsx:172-178 and packages/studio/src/components/StudioRightPanel.tsx:462-468
Pointer resizing is persisted through handlePanelResizeEnd, but the keyboard-accessible separator handlers call setLeftWidth / setRightWidth directly and never write preferences. A keyboard resize therefore appears to work, then is lost on reload. Centralizing a clamped set-and-persist/commitPanelWidth(side, width) path for both pointer completion and key handlers would fix this and likely give Copilot's already-reported pointer-up stale-state race one clean home too.
Ponytail review
Lean already. Ship.
CI is green at this exact head. Approve.
jrusso1020
left a comment
There was a problem hiding this comment.
Additive review at 4178332c. @Copilot commented (the panel-resize-end persist can read stale width during fast pointer interactions, usePanelLayout.ts:96); @magi reviewing in parallel. Weighted to Ular's ask + REVIEW_DISCIPLINE: does this actually simplify without dropping behavior or shuffling bytes?
Behavior-preservation — verified: a real simplification (net −304), not a byte-shuffle and not a silent behavior drop. The removed PlayerControls surface is exactly the duplicate seek path: SeekBar / SeekBarMarker / WorkAreaOverlay, the useSeekBarDrag hook (deleted — no remaining references anywhere in packages/studio/src), and the seekbar's local handleKeyDown. Everything else on the transport bar stays — play/pause (PlayPauseMorphIcon, onTogglePlay), speed (SpeedMenu), loop, mute, fullscreen, and in/out points are all still wired through usePlayerStore. Crucially the arrow-key frame-stepping the removed handleKeyDown provided is not lost: it's owned by usePlaybackKeyboard.ts (:103-110, ArrowLeft/ArrowRight → seek(stepFrameTime(...))) and playbackShortcuts.ts (PLAYBACK_FRAME_STEP_CODES), a document-level handler independent of the seekbar. So keyboard seek survives; only the redundant click/drag bar in the preview goes away — the stated intent (timeline owns seeking).
Verified — the responsive-defaults claim holds. getInitialPanelWidths (usePanelLayout.ts:21) derives left/right from viewport width but still floors both at 160 (:27-31), and handlePanelResizeMove re-clamps to [160, …] (:81-87), so "preserving existing narrow-screen minimums" is accurate.
Verdict: COMMENT — Ready on the merits. Genuine deletion-driven simplification with transport behavior verified intact; the one open item is Copilot's resize-persist staleness. (Deferring the stamp to the maintainer.)
Review by Jerrai (hyperframes)
9b2a1a7 to
a473c41
Compare
4178332 to
4bd03cb
Compare
a473c41 to
3237565
Compare
4bd03cb to
de48eae
Compare
jrusso1020
left a comment
There was a problem hiding this comment.
Re-review at de48eae3. @magi re-reviewing in parallel; independent verdict.
Copilot's resize-persist staleness note is addressed. usePanelLayout.ts now keeps panel widths in a panelWidthsRef that's updated synchronously on every resize step (updatePanelWidth writes panelWidthsRef.current[side] before/with the React state), and commitPanelWidth persists from that ref (writeStudioUiPreferences({ leftWidth / rightWidth: next })) rather than from a closure-captured state value — so a fast pointer drag can no longer persist a stale width. It also consolidates the bounds into clampPanelWidth(side, width) (left [160, innerWidth*0.5], right [160, 600]).
My prior Rule-7 behavior-preservation check still holds — this remains a genuine simplification (the duplicate preview seekbar + useSeekBarDrag removal, with arrow-key frame-seek preserved in usePlaybackKeyboard.ts), and the 160px panel minimums are still enforced (now in clampPanelWidth alongside getInitialPanelWidths). CI is CLEAN at de48eae3.
Verdict: COMMENT — ready on the merits; Copilot's note is resolved and the simplification is intact. Deferring the stamp; happy to APPROVE on @jrusso1020's go.
Review by Jerrai (hyperframes)
miguel-heygen
left a comment
There was a problem hiding this comment.
Exact-head delta re-review at de48eae3a30fcb745ba7b5404b4365066b489769.
The prior non-blocking persistence gaps are both cleanly resolved through one shared path:
usePanelLayout.ts:63-84centralizes clamping, ref synchronization, React state updates, and persistence.- Pointer movement updates
panelWidthsRef, so pointer-up persists the actual final width rather than potentially stale React state (usePanelLayout.ts:94-118). - Keyboard resizing now calls the same
adjustPanelWidthpath from both separators, so rapid steps accumulate and survive reload. usePanelLayout.test.ts:77-109pins both the pointer-up race and rapid keyboard persistence.
This preserves the original deletion-driven simplification while closing the only follow-ups from the first pass. Exact-head check-runs are complete with no failures or pending jobs.
Verdict: APPROVE
Reasoning: The corrective delta removes the stale-state race and unifies pointer/keyboard persistence without reintroducing duplicate resize logic.
— Magi
3237565 to
188be7b
Compare
de48eae to
085c638
Compare
188be7b to
38e21ea
Compare
085c638 to
02efd40
Compare
What
Updates Studio preview ergonomics: Design opens by default, large-screen panel proportions match the reviewed layout, resized widths persist, the timeline gets more default height, and preview transport controls are simplified.
Why
The preview had two competing seek surfaces and cramped default proportions. The timeline should own seeking while the preview keeps a compact transport bar.
How
Removes the duplicate preview seekbar and its dead drag helper, keeps play centered with unboxed utilities, and derives responsive panel defaults from viewport width while preserving existing narrow-screen minimums.
Test plan
Stack 6/6. Base: #2755. This PR contains only Studio workspace/chrome changes.