fix(studio): activate a composition at any path, not just compositions/ - #3547
Merged
miguel-heygen merged 1 commit intoAug 29, 2026
Merged
Conversation
The Comps panel sets activeCompositionPath to the selected file, but useCompositionStack's effect only pushed a stack level when that path started with compositions/. A project laying its comps out anywhere else, for example a generated multi-part build with parts/part-1.html next to the root index.html, matched no branch at all: the row highlighted and the URL hash updated while the stack silently kept the master mounted, so the canvas and timeline stayed on index.html and any edit landed in the root file instead of the part. Replaced the prefix test with a plain truthiness check, so the root stays on the master level and every other path pushes its own level. Label derivation is unchanged, matching CompositionsTab's own convention.
miguel-heygen
approved these changes
Aug 29, 2026
miguel-heygen
approved these changes
Aug 29, 2026
miguel-heygen
left a comment
Collaborator
There was a problem hiding this comment.
Reviewed end to end at adf9b0cceeb561fd5424e8cad73b781f5383a9ef.
Strengths
packages/studio/src/components/nle/useCompositionStack.ts:108preserves the explicit root-composition path while:111-124correctly routes every other truthy project-relative composition path through the existing encoded preview contract.packages/studio/src/components/nle/useCompositionStack.test.tsx:68-109covers the priorcompositions/behavior, the reportedparts/case, bare/deep paths, label preservation, and the root guard.
Verification
- Focused Vitest: 8/8 passed.
- Studio TypeScript:
tsc --noEmitpassed. - Synthetic local PR fixture, desktop + mobile: selecting
parts/part-1.htmlupdated the URL hash, preview iframe (PART ONE CANVAS), composition breadcrumb, and timeline (Part Title) together. - Browser console: no errors. The optional local FFmpeg/thumbnail probes were unavailable/timed out in the synthetic environment; the target composition preview endpoint loaded and rendered correctly.
- Required GitHub CI: 8/8 passed; no review comments or unresolved threads.
Verdict: APPROVE
Reasoning: The fix addresses the no-branch path bug without changing root behavior, is directly regression-tested, passes the relevant local and required CI gates, and the exact user-facing selection flow works at the reviewed SHA.
— Magi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes #3543. Selecting a composition in the Comps panel now actually switches the canvas and timeline to it, for any path, not only files under
compositions/.Why
useCompositionStack's activation effect ran an if/else-if chain:A path like
parts/part-1.htmlis notindex.html, does not start withcompositions/, and is not falsy, so it matched no branch at all and the effect did nothing. The Comps panel still highlighted the row and the URL hash still updated, but the stack kept the master mounted: the canvas and timeline stayed onindex.html, and, as the issue notes, any edit made there landed in the root file instead of the part.The reporter's setup is the case that exposes it, a generated multi-part build with
index.htmlplusparts/part-1.htmlthroughparts/part-4.html. Nothing requires a project's compositions to live undercompositions/; the server already serves any of them (GET /api/projects/<id>/preview/comp/parts/part-1.htmlreturns the right page, per the issue).How
Replaced the prefix test with a plain truthiness check, so the root composition stays on the master level and every other path pushes its own level. The final
elsenow covers null/empty.Label derivation is unchanged (
replace(/^compositions\//, "").replace(/\.html$/, "")), which is the same expressionCompositionsTabuses for the panel's own card labels, so acompositions/-relative project's labels are byte-identical to before andparts/part-1.htmlreads asparts/part-1.Test plan
Extended
useCompositionStack.test.tsxwith 6 cases: a parameterised set asserting a level is pushed with the rightidandpreviewUrlforcompositions/scene-a.html(the previously-working case, as a regression guard),parts/part-1.html(the issue's case), a barechapter-2.html, and a deepa/b/c/deep.html; plus a label assertion and a guard thatindex.htmlstill leaves the master alone.Mutation-tested: reverting only
useCompositionStack.tsand keeping the tests fails the three non-compositions/cases (stack length 1 instead of 2), while thecompositions/andindex.htmlcases still pass, which is exactly the reported split. 8/8 pass with the fix.I did not reproduce this in a running Studio: it needs a multi-part project and a live preview server, and the mechanism is fully determined by this effect's branch conditions, which the tests cover directly. The issue author already confirmed the runtime symptom headlessly with puppeteer.
lefthook run pre-commitall green (lint, format, fallow, typecheck, filesize, largefiles, tracked-artifacts, commitlint).