Skip to content

feat(studio): flat inspector — persisted pinning + multi-field Text#2125

Open
vanceingalls wants to merge 8 commits into
studio-flat-05-gradefrom
studio-flat-06-pinning-multifield
Open

feat(studio): flat inspector — persisted pinning + multi-field Text#2125
vanceingalls wants to merge 8 commits into
studio-flat-05-gradefrom
studio-flat-06-pinning-multifield

Conversation

@vanceingalls

@vanceingalls vanceingalls commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

Sixth and final PR in a 6-PR stack for the flat inspector redesign (see #2120 for the foundation and full stack list). Makes pinning an actually-observable, persisted feature — pinned groups now render first, always open, above a divider, and the pin state survives reload per element type — and flattens the multi-field Text case, retiring its legacy fallback.

Stack: #2120 (Foundation+Text) → #2121 (Style) → #2122 (Layout+Motion) → #2123 (Media) → #2124 (Grade) → #2125 (this).

Why

FlatGroup's pin button and PinnedZoneDivider existed since #2120 but nothing actually reordered a pinned group to the top or persisted the choice — pinning was invisible. Multi-field Text still fell back to the legacy stacked-sections component, the last remaining dependency on old UI in the migrated groups.

How

  • pinnedGroupsByElementType persisted to the existing studioUiPreferences.ts localStorage module (reused, not a new key), keyed per element kind (text/media/other).
  • usePersistedPinnedGroups(elementKind) hook wraps read/write with a togglePin that does a correct read-modify-write against the full map (the underlying preferences write is a shallow merge, not a deep one, so this hook is the single place that must not clobber other element kinds' pins — verified).
  • PinnedGroupRow is a new always-open wrapper (no collapse caret, "Pinned" badge) distinct from FlatGroup's normal accordion state.
  • PropertyPanelFlat.tsx refactored to a data-driven group-descriptor list, partitioned into pinned (rendered via PinnedGroupRow) and unpinned (rendered via FlatGroup's accordion) — every group from feat(studio): flat inspector foundation + Text group #2120feat(studio): flat inspector — Grade (color grading) group #2124 participates in the same mechanism.
  • FlatTextLayerList (originated layout — no design mock exists for this row; flagged for design review) lists each text field as a selectable "layer"; FlatTextSection's multi-field branch now uses it directly instead of delegating to the legacy TextSection, which no multi-field path in the flat inspector depends on anymore.
  • Still behind STUDIO_FLAT_INSPECTOR_ENABLED (default off).

Test plan

  • Pin/unpin reordering, persistence round-trip (including a malformed-storage-value edge case), and the multi-field layer list's select/add/remove interactions are all covered by real DOM-event tests with exact assertions.
  • A whole-branch final review across all 6 PRs' combined diff confirmed: the pin mechanism applies uniformly to all six groups with a single write path (no clobber risk), multi-field Text has zero remaining dependency on the legacy TextSection component, the full monorepo suite passes (1562+ tests, 0 failures), and the repo's fallow complexity/duplication gate passes clean.
  • Unit tests added/updated
  • Manual testing performed
  • Documentation updated (not applicable — internal Studio UI behind an off-by-default flag; multi-field Text layout flagged for design review before considered final)

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 8 commits July 10, 2026 18:28
…rences

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reads/writes the per-element-kind pinned-groups map added to
studioUiPreferences in the prior task, read-modify-writing the whole
map since writeStudioUiPreferences only shallow-merges top-level keys.
Review of the pin-aware group list refactor flagged the test name
claiming the group "closes" on unpin — it doesn't assert that, and
structurally the group re-opens (togglePin never touches openGroupId).
Retitled to describe only the return-to-stack behavior actually tested.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Originated layout, no design mock exists — flag for design review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Review proved the existing test didn't catch a broken stopPropagation
by temporarily removing it and confirming the suite still passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
FlatTextSection's multi-field branch (textFields.length > 1) now renders
FlatTextLayerList (Task 5) + the existing single-field FlatTextFieldEditor
for the active field, tracked via new local activeFieldKey state that
resyncs (useEffect) when the active field disappears from props. This
retires the legacy TextSection delegation entirely for that case; the
TextSection import is removed from propertyPanelFlatTextSection.tsx since
nothing else in the file referenced it.

Also updates propertyPanelSections.test.tsx and PropertyPanel.test.tsx,
which exercised/documented the old multi-field-falls-back-to-legacy-
TextSection behavior in comments and test titles — reworded to describe
the new flat path (assertions were already compatible and still pass).

Flag for reviewer: hideOwnHeading on the legacy TextSection component
(propertyPanelSections.tsx) was added in an earlier plan specifically for
this now-removed call site. It has no remaining consumer after this task
lands (PropertyPanel.tsx's legacy caller doesn't pass it). Left in place
per brief instruction — not deleting unilaterally, since that's a scope
decision for whoever reviews this task.

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: f3389dc. 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-05-grade branch from a9409d1 to dfdc68a Compare July 11, 2026 01:34
@vanceingalls vanceingalls force-pushed the studio-flat-06-pinning-multifield branch from f3389dc to 45a06a5 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