feat(studio): flat inspector — persisted pinning + multi-field Text#2125
Open
vanceingalls wants to merge 8 commits into
Open
feat(studio): flat inspector — persisted pinning + multi-field Text#2125vanceingalls wants to merge 8 commits into
vanceingalls wants to merge 8 commits into
Conversation
…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>
This was referenced Jul 10, 2026
Collaborator
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This was referenced Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

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 andPinnedZoneDividerexisted 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
pinnedGroupsByElementTypepersisted to the existingstudioUiPreferences.tslocalStorage module (reused, not a new key), keyed per element kind (text/media/other).usePersistedPinnedGroups(elementKind)hook wraps read/write with atogglePinthat 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).PinnedGroupRowis a new always-open wrapper (no collapse caret, "Pinned" badge) distinct fromFlatGroup's normal accordion state.PropertyPanelFlat.tsxrefactored to a data-driven group-descriptor list, partitioned into pinned (rendered viaPinnedGroupRow) and unpinned (rendered viaFlatGroup's accordion) — every group from feat(studio): flat inspector foundation + Text group #2120–feat(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 legacyTextSection, which no multi-field path in the flat inspector depends on anymore.STUDIO_FLAT_INSPECTOR_ENABLED(default off).Test plan
TextSectioncomponent, the full monorepo suite passes (1562+ tests, 0 failures), and the repo'sfallowcomplexity/duplication gate passes clean.