Skip to content

feat(studio): runtime-synced design panel + 3D props + split polish#1188

Merged
miguel-heygen merged 37 commits into
mainfrom
feat/keyframe-property-inspector
Jun 5, 2026
Merged

feat(studio): runtime-synced design panel + 3D props + split polish#1188
miguel-heygen merged 37 commits into
mainfrom
feat/keyframe-property-inspector

Conversation

@miguel-heygen
Copy link
Copy Markdown
Collaborator

Summary

  • Design panel Layout fields (X, Y, W, H, R) read GSAP-interpolated values from gsap.getProperty() at the current seek time — values update live when scrubbing
  • 3D transform properties added to SUPPORTED_PROPS: z, rotationX, rotationY, rotationZ, perspective, transformOrigin
  • Stronger clip selection border (full accent, glow shadow) and wider keyframe diamond tolerance (0.5% vs 0.05%)
  • DOM selection syncs to timeline selectedElementId on cold-load URL restore
  • Split restricted to media elements only (video/audio/img) — hidden for divs and compositions
  • Phosphor Scissors icon replaces inline SVG

Stacked on #1172.

@miguel-heygen miguel-heygen force-pushed the feat/keyframes-7-fixes-polish branch from 82a5989 to 6c8acf6 Compare June 4, 2026 04:57
@miguel-heygen miguel-heygen force-pushed the feat/keyframe-property-inspector branch 2 times, most recently from 0f7b0eb to 80f8959 Compare June 4, 2026 16:15
@miguel-heygen miguel-heygen force-pushed the feat/keyframes-7-fixes-polish branch 2 times, most recently from 790ef3f to 99fc9ee Compare June 4, 2026 16:40
@miguel-heygen miguel-heygen force-pushed the feat/keyframe-property-inspector branch 2 times, most recently from 8699a60 to 8b58fb0 Compare June 4, 2026 17:44
@miguel-heygen miguel-heygen force-pushed the feat/keyframes-7-fixes-polish branch 2 times, most recently from 1937dd3 to c048e70 Compare June 5, 2026 03:22
@miguel-heygen miguel-heygen force-pushed the feat/keyframe-property-inspector branch from ec0c763 to 69354c0 Compare June 5, 2026 03:22
Copy link
Copy Markdown
Collaborator

@jrusso1020 jrusso1020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Top-of-stack polish + 3D props. +362/-58. The 3D property additions are the most interesting cross-stack change — they extend the keyframeable surface from 2D transforms into 3D space.

3D transform properties — z, rotationX/Y/Z, perspective, transformOrigin

Two cross-browser concerns:

1. perspective placement matters

perspective set on an element creates 3D context for its children, not itself. If a user sets perspective: 800 on an element and expects that element's own 3D rotation to depth-render, they'll see a flat result. The Studio UI should either:

  • Auto-apply perspective to the parent when a 3D property is set on a child.
  • OR document the rule clearly in the property-panel UI (e.g., "set perspective on the parent of this element").

Without one of these, users will silently get flat-looking 3D and not understand why.

2. transformOrigin interaction with GSAP xPercent / yPercent

GSAP's xPercent: -50 / yPercent: -50 (centering pattern) interacts with transformOrigin. If the SUPPORTED_PROPS set now includes both transformOrigin and the existing transform props, verify the property panel doesn't allow conflicting combinations (e.g., setting xPercent: -50 and transformOrigin: "top left" simultaneously without a warning).

gsap.getProperty() at current seek time — design panel sync

Reading interpolated values from the live runtime is the right approach. Two questions:

  • Cost: getProperty() is cheap for a single element but called for every visible field on every scrub. With Layout (5 fields × multiple selected clips), this could be 20+ calls per scrub frame. Worth a memo with the scrub time as the dep so it batches per-frame.
  • Stale during transition: between seek() and the next runtime sync, getProperty() returns pre-seek values. Verify the design panel reads happen after the runtime has applied the seek (likely via the runtime bridge from #1169's optimistic-update pipeline).

Clip selection border (full accent + glow shadow) + 0.5% diamond tolerance

Both are UX-polish tunings. The 0.5% diamond tolerance (vs the prior 0.05%) is a 10× widening — confirm this matches user-tested expectations and doesn't make adjacent diamonds in dense timelines confusable.

DOM selection syncs to timeline selectedElementId on cold-load URL restore

Important for shareable Studio URLs. Verify the sync handles the case where selectedElementId references a stale element (no longer in the DOM after a script edit). Silent no-select or fallback to first element is fine; uncaught error is not.

Phosphor Scissors icon — duplicates #1189

Both #1189 and this PR mention the Phosphor Scissors icon. Once the stack merges in order, the second one is a no-op. Just flagging that the icon import lives in two PRs of the same stack.

Review by Jerrai (hyperframes specialist)

@miguel-heygen miguel-heygen force-pushed the feat/keyframes-7-fixes-polish branch from c048e70 to aae066c Compare June 5, 2026 05:55
@miguel-heygen miguel-heygen force-pushed the feat/keyframe-property-inspector branch 2 times, most recently from c12e51d to 437b02d Compare June 5, 2026 14:57
@miguel-heygen miguel-heygen force-pushed the feat/keyframes-7-fixes-polish branch 2 times, most recently from 0845d38 to 7b29dd3 Compare June 5, 2026 16:05
@miguel-heygen miguel-heygen force-pushed the feat/keyframe-property-inspector branch from 437b02d to 2a074bc Compare June 5, 2026 16:05
Base automatically changed from feat/keyframes-7-fixes-polish to feat/keyframes-6-dynamic-keyframes June 5, 2026 16:06
Revert totalTime nudge that caused black first frames in from() tweens.
Keep stale CSS offset cleanup. Regenerate baselines for offset cleanup.
Revert totalTime nudge that caused black first frames in from() tweens.
Keep stale CSS offset cleanup. Regenerate baselines for offset cleanup.
…ation

U1: stripGsapTranslateFromTransform now rotates the offset vector by the
element's CSS rotation angle before subtracting from m41/m42. Fixes
elements drifting from cursor during drag when rotated.

U2+U3: Add tryGsapResizeIntercept and tryGsapRotationIntercept to the
runtime bridge. Resize and rotation handle changes now create keyframes
via the same async pipeline as position drag. CSS path guards prevent
double-persistence for GSAP-animated elements.
…yBoxSizes guard

- Fix overlay bounding box jump: reapplyBoxSizes now skips elements whose
  width/height are animated by GSAP (gsapAnimatesProperty check prevents
  studio CSS from overwriting GSAP interpolated values)
- Delete All Keyframes removes entire animation (handleGsapDeleteAnimation)
  with fallback to first animation when no keyframed anim exists
- Wire split clip through App → StudioPreviewArea → NLELayout → Timeline
  (onSplitElement prop, toolbar button, S hotkey, clip context menu)
- Add onContextMenu to TimelineClip for right-click clip context menu
Sub-compositions (data-composition-src) cannot be meaningfully split —
the clone would load the same source and fight for the same timeline.
Block with a specific toast message and disable in the context menu.
…rties

The Layout section (X, Y, W, H, R) now reads GSAP-interpolated values
from the runtime via gsap.getProperty() at the current seek time. When
an element has GSAP animations, the fields reflect the actual interpolated
position/size/rotation instead of the CSS defaults.

Also adds 3D transform properties to SUPPORTED_PROPS: z, rotationX,
rotationY, rotationZ, perspective, transformOrigin.
… tolerance

- Selected clip: full accent border (was 38% opacity), subtle glow shadow
- Keyframe diamond at playhead: tolerance 0.5% (was 0.05% — too tight at
  high zoom levels, causing diamonds to never highlight)
Extract useAnimatedPropertyCommit hook that handles the three-case commit
logic: keyframed → add-keyframe, flat → convert + add, no animation →
create + convert + add. Wire Z, Scale, RotX, RotY design panel fields
and 2D Layout fields through this unified pipeline.

Export readAllAnimatedProperties and readGsapProperty from the runtime
bridge so the commit helper can read all animated props for backfill.
These design plans were accidentally committed and should not be in
the PR.
@miguel-heygen miguel-heygen force-pushed the feat/keyframe-property-inspector branch from 06325c3 to eb8f448 Compare June 5, 2026 16:10
@miguel-heygen miguel-heygen merged commit 1bdb2d4 into main Jun 5, 2026
11 of 12 checks passed
@miguel-heygen miguel-heygen deleted the feat/keyframe-property-inspector branch June 5, 2026 16:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants