Skip to content

feat(studio): flat inspector — Layout + Motion groups#2122

Open
vanceingalls wants to merge 11 commits into
studio-flat-02-stylefrom
studio-flat-03-layout-motion
Open

feat(studio): flat inspector — Layout + Motion groups#2122
vanceingalls wants to merge 11 commits into
studio-flat-02-stylefrom
studio-flat-03-layout-motion

Conversation

@vanceingalls

@vanceingalls vanceingalls commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

Third PR in a 6-PR stack for the flat inspector redesign (see #2120 for the foundation and full stack list). Adds the flat Layout group (X/Y/W/H/Angle geometry rows with keyframe gutters, Z-index, Flex, a wrapped 3D transform sub-view) and the flat Motion group (Timing row, effect-card list), each wired into the accordion, plus a cross-group fix reconciling their timing basis.

Stack: #2120 (Foundation+Text) → #2121 (Style) → #2122 (this) → #2123 (Media) → #2124 (Grade) → #2125 (Pinning + multi-field Text).

Why

Layout and Motion are the two groups most entangled with GSAP keyframe state — an element's timing (start/duration) has to agree between Layout's keyframe-seek gutter and Motion's Timing row, or keyframe diamonds and prev/next-arrow navigation land in the wrong place.

How

  • FlatLayoutSection composes geometry/Z-index/Flex/3D-transform sub-blocks; the 3D transform view is the existing component nested in a new flat wrapper, not rebuilt.
  • FlatMotionSection composes a new FlatTimingRow with the existing effect-card list (given a new flat collapsed-header variant).
  • Cross-group fix included in this PR: a coherence review across Layout+Motion found their keyframe-seek bases disagreed for elements with animations but no explicit data-duration (Layout used a naive duration ?? 1, Motion correctly inferred from the GSAP tween). Fixed via a new shared deriveElementTiming helper both groups now read from, plus a follow-up fix threading the corrected basis into the keyframe diamond active-state/arrow-navigation calculation.
  • Still behind STUDIO_FLAT_INSPECTOR_ENABLED (default off).

Test plan

  • Every row/primitive has a real DOM-event test with exact assertions.
  • The timing-basis fix was caught by a whole-plan coherence review (not per-task review) and independently verified against both groups' keyframe rendering before and after.
  • Full monorepo suite green; oxlint/oxfmt/fallow clean.
  • Unit tests added/updated
  • Manual testing performed
  • Documentation updated (not applicable — internal Studio UI behind an off-by-default flag)

vanceingalls commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

@miga-heygen miga-heygen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed as part of the 15-PR edit-panel redesign stack. Full stack review posted on #2120. No blockers on this PR. — Miga

vanceingalls and others added 11 commits July 10, 2026 18:28
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Thread the Layout-group values through PropertyPanel -> PropertyPanelFlat
and add the third FlatGroup to the one-open/pin accordion (unconditional,
matching legacy Layout). Default-open Layout when neither Text nor Style
applies.

Fix the Flex double-render: the legacy StyleSections still renders its own
Flex Section, and the new flat Layout group renders its own LayoutFlexBlock.
Add an additive optional hideFlex prop to StyleSections and pass it on the
flat path so Flex renders exactly once (from the flat Layout group). Non-flat
callers omit it and are unchanged.

Extract the shared onLivePreviewProps closure into gsapLivePreview.ts (it was
duplicated inline in the legacy path) so PropertyPanel.tsx stays within the
600-LOC studio gate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… and Motion groups

Whole-plan coherence review (Plan 3a Layout + Plan 3b Motion) found that
Layout's keyframe gutter and Motion's Timing row independently derived an
element's start/duration and disagreed whenever an element had animations
but no explicit data-duration: Motion correctly inferred the range from the
element's GSAP tweens, while Layout's keyframe gutter fell back to a naive
`duration ?? 1`, so clicking a keyframe percentage in Layout could seek to a
different absolute time than what Motion's Timing row displayed.

Extract deriveElementTiming (propertyPanelFlatTimingDerivation.ts) as the
single shared basis both paths now consume: FlatTimingRow (Motion) and
PropertyPanelFlat's own elStart/elDuration (Layout's keyframe gutter and 3D
Transform block). PropertyPanelFlat now recomputes this basis itself from
its own element/gsapAnimations props instead of trusting the parent's naive
value, so PropertyPanel.tsx (and its legacy non-flat panel) is untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…basis in the flat Layout group

Follow-up to 684ec4e: that fix corrected the seek target for Layout's
keyframe gutter via deriveElementTiming, but currentPct — which drives
KeyframeNavigation's diamond active/inactive state and prev/next arrow
targeting — still used PropertyPanel's naive elStart=0/elDuration=1
basis. For an element with animations but no explicit data-duration,
seeking to a keyframe's real absolute time no longer lit that
keyframe's diamond as active, and the prev/next arrows targeted the
wrong keyframes.

Thread currentTime into PropertyPanelFlat (swapping the now-redundant
currentPct prop 1-for-1, so PropertyPanel.tsx's line count is
unchanged) and recompute currentPct there from the same
deriveElementTiming basis already used for the seek fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Final current-head pass: bb1be1f. Reviewed the stack boundaries and current diff against the flat-inspector contracts; required checks have no failures/pending checks and no unresolved review threads remain. No new drift found; residual notes are non-blocking.

@vanceingalls vanceingalls force-pushed the studio-flat-02-style branch from ec3ad42 to e02e0f5 Compare July 11, 2026 01:34
@vanceingalls vanceingalls force-pushed the studio-flat-03-layout-motion branch from bb1be1f to 906d740 Compare July 11, 2026 01:34

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Superseding earlier approval: the latest max-review pass found confirmed correctness issues in this flat-inspector stack (identity/selector-index state, hide-all write races, timing inference, slider pointer/keyboard/reset semantics, and duplicate React keys). Hold merge and require fixes plus re-review on the current stack head.

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.

3 participants