Summary
Since #1763 removed the timeline keyframe-drag affordance, there is no GUI gesture left to retime an existing keyframe in time while preserving its value and easing. The only ways to move a keyframe in time via the UI now (delete + re-add at playhead, toggle-at-playhead) bake the current computed values and drop the explicit ease — so the author loses the keyframe they were trying to move.
The interesting part: the capability to retime-while-preserving still exists in the reducer — it's just not wired to any UI action anymore.
What still exists vs. what's reachable
Reading the served Studio bundle (dist/studio/assets/index-*.js, v0.7.18), the reducer handles a setGsapKeyframe action that does exactly the right thing:
case "setGsapKeyframe":
return nAe(t, e.animationId, e.keyframeIndex, e.position, e.value, e.ease);
// nAe: position = e.position ?? current ; value = e.value ?? {...existing.properties} ; ease = e.ease ?? existing.ease
// → passing ONLY a new `position` retimes the keyframe while keeping its value AND ease.
But setGsapKeyframe appears only twice in the whole bundle — the reducer case above and the validation switch. No UI code dispatches { type: "setGsapKeyframe", position: … }. The keyframe diamond now binds only onClick (select + seek) and onContextMenu, and the context menu wires only "change ease" and "delete" — there is no "set time / move to playhead" action. So the preserving-retime path is reachable from the SDK/code but dead from the GUI.
Request
Re-expose keyframe retiming through a UI gesture by dispatching the existing setGsapKeyframe with a new position (preserving value + ease). A drag affordance isn't required — a menu entry is enough. For example, add to the keyframe context menu:
- "Move keyframe to playhead" →
setGsapKeyframe({ animationId, keyframeIndex, position: playheadPercent }), and/or
- an editable time / percentage field for the selected keyframe.
This reuses code that's already present; it's a wiring task, not new engine work.
Use case / motivation
Our workflow has a non-technical author posing keyframes by gesture in the Studio, then a technical editor refining in source. Retiming is currently the one operation that can't be done at the gesture level without destroying the keyframe — so every retime has to round-trip through hand-editing tl.to(sel, { keyframes: { … } }) in code. Restoring a gesture that retimes-in-place (preserving value + ease) would let the author iterate on timing directly, which is the common case.
Environment
Summary
Since #1763 removed the timeline keyframe-drag affordance, there is no GUI gesture left to retime an existing keyframe in time while preserving its value and easing. The only ways to move a keyframe in time via the UI now (delete + re-add at playhead, toggle-at-playhead) bake the current computed values and drop the explicit ease — so the author loses the keyframe they were trying to move.
The interesting part: the capability to retime-while-preserving still exists in the reducer — it's just not wired to any UI action anymore.
What still exists vs. what's reachable
Reading the served Studio bundle (
dist/studio/assets/index-*.js, v0.7.18), the reducer handles asetGsapKeyframeaction that does exactly the right thing:But
setGsapKeyframeappears only twice in the whole bundle — the reducer case above and the validation switch. No UI code dispatches{ type: "setGsapKeyframe", position: … }. The keyframe diamond now binds onlyonClick(select + seek) andonContextMenu, and the context menu wires only "change ease" and "delete" — there is no "set time / move to playhead" action. So the preserving-retime path is reachable from the SDK/code but dead from the GUI.Request
Re-expose keyframe retiming through a UI gesture by dispatching the existing
setGsapKeyframewith a newposition(preservingvalue+ease). A drag affordance isn't required — a menu entry is enough. For example, add to the keyframe context menu:setGsapKeyframe({ animationId, keyframeIndex, position: playheadPercent }), and/orThis reuses code that's already present; it's a wiring task, not new engine work.
Use case / motivation
Our workflow has a non-technical author posing keyframes by gesture in the Studio, then a technical editor refining in source. Retiming is currently the one operation that can't be done at the gesture level without destroying the keyframe — so every retime has to round-trip through hand-editing
tl.to(sel, { keyframes: { … } })in code. Restoring a gesture that retimes-in-place (preserving value + ease) would let the author iterate on timing directly, which is the common case.Environment