diff --git a/packages/studio/src/components/editor/PropertyPanelFlat.tsx b/packages/studio/src/components/editor/PropertyPanelFlat.tsx index 05c12d31fe..44745a528e 100644 --- a/packages/studio/src/components/editor/PropertyPanelFlat.tsx +++ b/packages/studio/src/components/editor/PropertyPanelFlat.tsx @@ -19,6 +19,7 @@ import { createGsapLivePreview } from "./gsapLivePreview"; import { formatTextFieldPreview } from "./propertyPanelSections"; import { STUDIO_GSAP_PANEL_ENABLED } from "./manualEditingAvailability"; import { useColorGradingController } from "./useColorGradingController"; +import { usePlayerStore } from "../../player"; import { FlatColorGradingAccessory, FlatColorGradingSection, @@ -252,6 +253,17 @@ export function PropertyPanelFlat({ // just toggled. Two ids, not one: the clicked (newly-opening/closing) group // AND whichever group was open immediately before the click and got // implicitly closed by it — both freshly-mounted headers need to animate. + // When the inline timeline ease button focuses a segment on this element, + // force the Motion group open so its AnimationCard (which only mounts while + // the group is expanded) can consume the focus and reveal the ease editor. + const focusedEaseSegment = usePlayerStore((s) => s.focusedEaseSegment); + useEffect(() => { + if (!focusedEaseSegment) return; + if (gsapAnimations.some((a) => a.id === focusedEaseSegment.animationId)) { + setOpenGroupId("motion"); + } + }, [focusedEaseSegment, gsapAnimations]); + const [justToggledIds, setJustToggledIds] = useState([]); const justToggledTimeoutRef = useRef | null>(null); useEffect(() => { diff --git a/packages/studio/src/components/editor/propertyPanelFlatMotionSection.tsx b/packages/studio/src/components/editor/propertyPanelFlatMotionSection.tsx index 7458ad508a..9057cce43a 100644 --- a/packages/studio/src/components/editor/propertyPanelFlatMotionSection.tsx +++ b/packages/studio/src/components/editor/propertyPanelFlatMotionSection.tsx @@ -12,6 +12,7 @@ import { type GsapAnimationEditCallbacks, } from "./gsapAnimationCallbacks"; import { deriveElementTiming } from "./propertyPanelFlatTimingDerivation"; +import { usePlayerStore } from "../../player"; export function FlatTimingRow({ element, @@ -144,6 +145,8 @@ export function FlatMotionSection({ : "metric"; track(control, property); }; + const focusedEaseSegment = usePlayerStore((s) => s.focusedEaseSegment); + const setFocusedEaseSegment = usePlayerStore((s) => s.setFocusedEaseSegment); return (
@@ -176,6 +179,10 @@ export function FlatMotionSection({ animation={anim} defaultExpanded={index === 0} flat + focusedSegment={ + focusedEaseSegment?.animationId === anim.id ? focusedEaseSegment : null + } + onFocusSegmentConsumed={() => setFocusedEaseSegment(null)} onUpdateProperty={(animationId, property, value) => { trackProperty(property); callbacks.onUpdateProperty(animationId, property, value);