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 and others added 8 commits July 9, 2026 16:13
…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>

vanceingalls commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

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.

1 participant