Skip to content

feat(metadata): show unsaved changes warning for sidebar navigation attempts#4506

Open
olehrybak wants to merge 3 commits intobox:masterfrom
olehrybak:metadata-warning-modal-improvements
Open

feat(metadata): show unsaved changes warning for sidebar navigation attempts#4506
olehrybak wants to merge 3 commits intobox:masterfrom
olehrybak:metadata-warning-modal-improvements

Conversation

@olehrybak
Copy link
Copy Markdown

@olehrybak olehrybak commented Apr 16, 2026

Unsaved changes warning modal was previously triggered in metadata sidebar only when a user was selecting a new template when edit was in progress. This PR extends this logic to also show the warning modal when a user tries to navigate to other sidebar tabs (i.e. when sidebar router history is changing).

Changes

  • Added history.block navigation guard that intercepts sidebar tab switches while the metadata editor is open (gated behind isConfidenceScoreReviewEnabled feature flag)
  • On "Discard Changes": removes the blocker, clears the editor, and completes the pending navigation via history.push
  • On "Continue Editing": re-syncs the URL back to /metadata via history.replace to fix any URL desync caused by external navigators (e.g., Box AI button in EndUserApp), then re-installs the blocker
  • Blocker is automatically cleaned up when editing ends or the component unmounts

Summary by CodeRabbit

  • New Features
    • Navigation from the content view is deferred when metadata editing is active; attempting to switch files opens the unsaved-changes modal and preserves the intended destination until discard.
  • Bug Fixes
    • Prevents accidental navigation away from the metadata editor; discarding applies pending navigation, continuing re-syncs the metadata URL, and cleanup removes the navigation blocker on close/unmount.
  • Tests
    • Added coverage for navigation blocking, modal flows, URL resync, discard behavior, and cleanup.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 16, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 16, 2026

Walkthrough

Introduces a navigation guard when metadata editing (confidence-score-review feature) is active: attempted navigations are blocked via history.block, stored as a pending destination, and an unsaved-changes modal is shown; discarding proceeds to the stored destination, continuing re-syncs URL to metadata, and cleanup/unblock occurs on discard or unmount.

Changes

Cohort / File(s) Summary
Metadata Sidebar (redesign)
src/elements/content-sidebar/MetadataSidebarRedesign.tsx
Adds history.block registration when editing with confidence-score-review enabled, stores pendingNavLocation, exposes new callbacks/props (onEditingStateChange, setWarningModalOpenCallback, setWarningModalDiscardCallback), re-syncs URL via history.replace on continue, prioritizes resolving pending blocked navigation on discard, and cleans up/unblocks on unmount or file change.
Metadata Sidebar (legacy props)
src/elements/content-sidebar/MetadataSidebar.js
Adds the same three optional external callback props to the public prop types: onEditingStateChange, setWarningModalOpenCallback, setWarningModalDiscardCallback.
Content Preview integration
src/elements/content-preview/ContentPreview.js
Tracks isMetadataEditing, defers navigation by storing pendingNavFileId and invoking a sidebar unsaved-changes modal callback when editing + feature enabled; injects editing-state and modal callbacks into sidebar props and implements handlers to discard/defer navigation. Also imports/uses isFeatureEnabled.
Sidebar unit tests
src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx
Updates test helper to use createMemoryHistory with spies on history.block/push/replace; adds navigation-blocking tests validating blocker installation conditioned on the feature flag, modal behavior on attempted navigation, discard pushes pending location, continue replaces URL, and unblock called on unmount; adds mount/discard callback assertions.
ContentPreview unit tests
src/elements/content-preview/__tests__/ContentPreview.test.js
Adds tests for navigateToIndex() covering the metadata unsaved-changes guard (feature-flag gated): defers navigation when editing, opens modal, stashes target file id; tests for storing modal callbacks and for discard callback navigating to pending id.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant CP as ContentPreview
    participant MSR as MetadataSidebarRedesign
    participant Router as History API
    participant Modal as Unsaved Changes Modal

    User->>CP: Click to navigate to another file
    CP->>CP: isMetadataEditing? (feature flag)
    alt Editing + feature enabled
        CP->>MSR: request sidebar open / navigation intent
        MSR->>Router: history.block(blockerCallback)
        MSR->>Router: (navigation attempted) -> blockerCallback(to)
        Router->>MSR: returns blocked destination (pendingNavLocation)
        MSR->>Modal: open unsaved-changes modal
        User->>Modal: Choose "Discard"
        Modal->>MSR: handleDiscardUnsavedChanges
        MSR->>Router: unblock()
        MSR->>Router: history.push(pendingNavLocation)
        MSR->>MSR: clear pendingNavLocation
    else Not editing or feature disabled
        CP->>Router: history.push(target)
    end

    Note right of MSR: On "Continue" -> history.replace("/metadata") and clear pendingNavLocation
    Note right of MSR: On unmount -> call unblock() if installed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

ready-to-merge

Suggested reviewers

  • Lindar90
  • dlasecki-box
  • jackiejou

Poem

🐇 I hopped between routes with care and grace,
Held back the wanderer from leaving this place.
"Unsaved!" I thumped — a soft, hopeful sound,
Discard and I'll leap, or stay safe and resound. 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description clearly explains the motivation, lists specific changes, and describes the behavior of the discard/continue editing flows, but does not follow the repository's required template structure. While informative, the description should follow the template structure provided in the repository, which appears to focus on merge queue instructions and reviewer management.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main feature: adding an unsaved changes warning for sidebar navigation attempts, which matches the core changes across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@olehrybak olehrybak marked this pull request as ready for review April 17, 2026 09:44
@olehrybak olehrybak requested review from a team as code owners April 17, 2026 09:44
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/elements/content-sidebar/MetadataSidebarRedesign.tsx (1)

238-254: ⚠️ Potential issue | 🟡 Minor

Navigation-discard branch skips some editor-state cleanup.

The new pendingNavLocation branch clears editingTemplate but, unlike handleCancel, doesn't call clearExtractError() or setShouldShowOnlyReviewFields(false). If the user navigates away and returns to the sidebar without a remount (e.g., SPA route back), the stale extract error and review-filter flag will persist.

🧹 Proposed consolidation
     const handleDiscardUnsavedChanges = () => {
         if (pendingNavLocation && isConfidenceScoreReviewEnabled) {
             unblockRouterHistory();
-            setEditingTemplate(null);
+            handleCancel();
             history.push(pendingNavLocation);
             setPendingNavLocation(null);
         } else if (pendingTemplateToEdit) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/elements/content-sidebar/MetadataSidebarRedesign.tsx` around lines 238 -
254, The pendingNavLocation branch in handleDiscardUnsavedChanges clears
editingTemplate but omits other editor cleanup done by handleCancel; update that
branch to invoke clearExtractError() and setShouldShowOnlyReviewFields(false)
(the same cleanup handleCancel performs) before calling unblockRouterHistory(),
history.push(pendingNavLocation) and clearing pendingNavLocation so stale
extract errors and review-filter flags are reset when navigating away; ensure
you reference handleDiscardUnsavedChanges, pendingNavLocation,
clearExtractError, and setShouldShowOnlyReviewFields when making the change.
🧹 Nitpick comments (1)
src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx (1)

599-611: Tighten the discard assertion to guard against re-sync regressions.

Given that the production handler for "Continue Editing" calls history.replace('/metadata'), an erroneous invocation of that same path during the discard flow (see concern on MetadataSidebarRedesign.tsx around handleUnsavedChangesModalOpen) would go undetected by this test. Add a negative assertion so a future regression that re-syncs the URL after a discard is caught.

✅ Proposed test strengthening
             expect(mockHistory.push).toHaveBeenCalledWith(expect.objectContaining({ pathname: '/boxai' }));
+            expect(mockHistory.replace).not.toHaveBeenCalled();
             expect(screen.queryByText('Unsaved Changes')).not.toBeInTheDocument();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx`
around lines 599 - 611, Tighten the discard test by asserting the discard flow
does not re-sync to the editing path: after clicking the "Discard Changes"
button (in the test "should navigate to pending location on discard"), keep the
existing expect(mockHistory.push).toHaveBeenCalledWith(...) check and add a
negative assertion that mockHistory.replace was not invoked with the editing
metadata path (e.g.,
expect(mockHistory.replace).not.toHaveBeenCalledWith(expect.objectContaining({
pathname: '/metadata' }))). This ensures handleUnsavedChangesModalOpen
regressions that call history.replace('/metadata') during discard are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/elements/content-sidebar/MetadataSidebarRedesign.tsx`:
- Around line 196-208: handleUnsavedChangesModalOpen currently reads a stale
pendingNavLocation because handleDiscardUnsavedChanges calls
setPendingNavLocation(null) and setIsUnsavedChangesModalOpen(false) together;
change the implementation so the discard path clears pendingNavLocation before
closing the modal (e.g., setPendingNavLocation(null) and only after that call
setIsUnsavedChangesModalOpen(false), or alternatively add a ref like
isDiscardingRef toggled in handleDiscardUnsavedChanges and checked inside
handleUnsavedChangesModalOpen to skip the history.replace logic), and update the
comment in handleUnsavedChangesModalOpen from "is the URL was updated" to "if
the URL was updated"; ensure the logic still calls unblockRouterHistory(),
history.replace(`/${SIDEBAR_VIEW_METADATA}`) and blockRouterHistory() only when
appropriate.

---

Outside diff comments:
In `@src/elements/content-sidebar/MetadataSidebarRedesign.tsx`:
- Around line 238-254: The pendingNavLocation branch in
handleDiscardUnsavedChanges clears editingTemplate but omits other editor
cleanup done by handleCancel; update that branch to invoke clearExtractError()
and setShouldShowOnlyReviewFields(false) (the same cleanup handleCancel
performs) before calling unblockRouterHistory(),
history.push(pendingNavLocation) and clearing pendingNavLocation so stale
extract errors and review-filter flags are reset when navigating away; ensure
you reference handleDiscardUnsavedChanges, pendingNavLocation,
clearExtractError, and setShouldShowOnlyReviewFields when making the change.

---

Nitpick comments:
In `@src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx`:
- Around line 599-611: Tighten the discard test by asserting the discard flow
does not re-sync to the editing path: after clicking the "Discard Changes"
button (in the test "should navigate to pending location on discard"), keep the
existing expect(mockHistory.push).toHaveBeenCalledWith(...) check and add a
negative assertion that mockHistory.replace was not invoked with the editing
metadata path (e.g.,
expect(mockHistory.replace).not.toHaveBeenCalledWith(expect.objectContaining({
pathname: '/metadata' }))). This ensures handleUnsavedChangesModalOpen
regressions that call history.replace('/metadata') during discard are caught.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d35e134e-3cd8-432f-add2-98a9975f79f8

📥 Commits

Reviewing files that changed from the base of the PR and between 6a64717 and 341036c.

📒 Files selected for processing (2)
  • src/elements/content-sidebar/MetadataSidebarRedesign.tsx
  • src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx

Comment thread src/elements/content-sidebar/MetadataSidebarRedesign.tsx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/elements/content-preview/ContentPreview.js`:
- Around line 1194-1203: The deferred navigation path that sets pendingNavFileId
in ContentPreview.js and calls sidebarOpenUnsavedModal(true) must be centralized
through the existing onBeforeNavigate guard and must clear pendingNavFileId on
modal close/cancel; update the branch in the isMetadataEditing block to set
pendingNavFileId and invoke the sidebar modal but do not perform direct
navigation from handleSetWarningModalDiscardCallback—instead have the discard
callback call the same onBeforeNavigate resolution path (or trigger the existing
onBeforeNavigate handler) so navigation flows through that guard, and ensure any
cancel/close code (the modal close/cancel handler you already have) clears
pendingNavFileId to avoid stale navigation; apply the identical change to the
other occurrence around lines 1487-1494.

In `@src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx`:
- Around line 133-135: The test is passing the feature flags wrapped in {
wrapperProps: { features } } but the helper (renderComponent / render) now
expects the raw features object as the second argument; update the render calls
for MetadataSidebarRedesign to pass features directly (e.g.,
renderComponent(<MetadataSidebarRedesign {...defaultProps} {...props} />,
features) or render(..., features)) instead of { wrapperProps: { features } },
and make the same change for the other occurrence around lines 293-296 so the
disabled-AI path receives the correct feature flag shape.

In `@src/elements/content-sidebar/MetadataSidebar.js`:
- Around line 47-49: The prop setWarningModalDiscardCallback is currently typed
as a registration callback but is used as a zero-argument discard notification
in MetadataSidebarRedesign and ContentPreview; change the prop contract to a
zero-argument callback (setWarningModalDiscardCallback?: () => void) and update
all call sites to invoke it with no arguments (including where
MetadataSidebar.js currently declares/exports the prop and any consumers), or
alternatively make the consumers register a handler if you prefer a registration
pattern—ensure MetadataSidebarRedesign and ContentPreview match the chosen
contract so the exported prop type and implementations are consistent.

In `@src/elements/content-sidebar/MetadataSidebarRedesign.tsx`:
- Around line 224-230: When MetadataSidebarRedesign unmounts it may leave the
parent thinking editing is active and a stale modal opener set; add cleanup to
the existing effects so they reset the parent state and callback on unmount: in
the effect that calls onEditingStateChange (which watches editingTemplate and
onEditingStateChange) return a cleanup that calls onEditingStateChange?.(false),
and in the effect that sets setWarningModalOpenCallback (which depends on
setWarningModalOpenCallback and handleUnsavedChangesModalOpen) return a cleanup
that calls setWarningModalOpenCallback?.(undefined) to clear the stale modal
opener (use the existing symbols: MetadataSidebarRedesign, onEditingStateChange,
setWarningModalOpenCallback, handleUnsavedChangesModalOpen).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e1ed7f4d-c9ae-45fc-883e-1a5619ce86a3

📥 Commits

Reviewing files that changed from the base of the PR and between 2b50100 and f3f3303.

📒 Files selected for processing (5)
  • src/elements/content-preview/ContentPreview.js
  • src/elements/content-preview/__tests__/ContentPreview.test.js
  • src/elements/content-sidebar/MetadataSidebar.js
  • src/elements/content-sidebar/MetadataSidebarRedesign.tsx
  • src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx

Comment on lines +1194 to +1203
// Internal guard: delegate to sidebar's unsaved changes modal when editing
if (
isMetadataEditing &&
this.sidebarOpenUnsavedModal &&
isFeatureEnabled(features, 'metadata.confidenceScore.enabled')
) {
this.pendingNavFileId = fileId;
this.sidebarOpenUnsavedModal(true);
return;
}
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.

⚠️ Potential issue | 🟠 Major

Tighten the deferred navigation lifecycle before release.

This path stores pendingNavFileId and later navigates directly from handleSetWarningModalDiscardCallback, which skips onBeforeNavigate. It also never clears pendingNavFileId when the user chooses Continue Editing, so a later unrelated discard can navigate to a stale file because the sidebar calls the discard callback for all discard flows.

Please centralize the deferred resolution through the same navigation guard path and clear the pending file id on modal close/cancel.

Also applies to: 1487-1494

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/elements/content-preview/ContentPreview.js` around lines 1194 - 1203, The
deferred navigation path that sets pendingNavFileId in ContentPreview.js and
calls sidebarOpenUnsavedModal(true) must be centralized through the existing
onBeforeNavigate guard and must clear pendingNavFileId on modal close/cancel;
update the branch in the isMetadataEditing block to set pendingNavFileId and
invoke the sidebar modal but do not perform direct navigation from
handleSetWarningModalDiscardCallback—instead have the discard callback call the
same onBeforeNavigate resolution path (or trigger the existing onBeforeNavigate
handler) so navigation flows through that guard, and ensure any cancel/close
code (the modal close/cancel handler you already have) clears pendingNavFileId
to avoid stale navigation; apply the identical change to the other occurrence
around lines 1487-1494.

Comment on lines +133 to +135
const renderResult = render(<MetadataSidebarRedesign {...defaultProps} {...props} />, {
wrapperProps: { features },
});
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.

⚠️ Potential issue | 🟡 Minor

Fix the stale nested wrapperProps call after changing the helper signature.

renderComponent now expects the raw features object as its second argument, but the existing disabled-AI test still passes { wrapperProps: { features } }. That means the feature flag shape is wrong and the test may not exercise the disabled path.

Proposed test fix
         renderComponent(
             { isBoxAiSuggestionsEnabled: false },
-            { wrapperProps: { features: { 'metadata.aiSuggestions.enabled': false } } },
+            { 'metadata.aiSuggestions.enabled': false },
         );

Also applies to: 293-296

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/elements/content-sidebar/__tests__/MetadataSidebarRedesign.test.tsx`
around lines 133 - 135, The test is passing the feature flags wrapped in {
wrapperProps: { features } } but the helper (renderComponent / render) now
expects the raw features object as the second argument; update the render calls
for MetadataSidebarRedesign to pass features directly (e.g.,
renderComponent(<MetadataSidebarRedesign {...defaultProps} {...props} />,
features) or render(..., features)) instead of { wrapperProps: { features } },
and make the same change for the other occurrence around lines 293-296 so the
disabled-AI path receives the correct feature flag shape.

Comment on lines +47 to +49
onEditingStateChange?: (isEditing: boolean) => void,
setWarningModalOpenCallback?: (handleWarningModalOpen: (isOpen: boolean) => void) => void,
setWarningModalDiscardCallback?: (handleWarningModalDiscard: () => void) => void,
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.

⚠️ Potential issue | 🟠 Major

Align the discard callback contract across sidebar implementations.

setWarningModalDiscardCallback is typed here as a registration callback, but MetadataSidebarRedesign invokes it as a zero-argument discard notification and ContentPreview implements it that way. Consumers typed against this exported prop can wire the wrong contract.

Proposed contract alignment
     onEditingStateChange?: (isEditing: boolean) => void,
     setWarningModalOpenCallback?: (handleWarningModalOpen: (isOpen: boolean) => void) => void,
-    setWarningModalDiscardCallback?: (handleWarningModalDiscard: () => void) => void,
+    setWarningModalDiscardCallback?: () => void,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/elements/content-sidebar/MetadataSidebar.js` around lines 47 - 49, The
prop setWarningModalDiscardCallback is currently typed as a registration
callback but is used as a zero-argument discard notification in
MetadataSidebarRedesign and ContentPreview; change the prop contract to a
zero-argument callback (setWarningModalDiscardCallback?: () => void) and update
all call sites to invoke it with no arguments (including where
MetadataSidebar.js currently declares/exports the prop and any consumers), or
alternatively make the consumers register a handler if you prefer a registration
pattern—ensure MetadataSidebarRedesign and ContentPreview match the chosen
contract so the exported prop type and implementations are consistent.

Comment on lines +224 to +230
useEffect(() => {
onEditingStateChange?.(!!editingTemplate);
}, [editingTemplate, onEditingStateChange]);

useEffect(() => {
setWarningModalOpenCallback?.(handleUnsavedChangesModalOpen);
}, [setWarningModalOpenCallback, handleUnsavedChangesModalOpen]);
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.

⚠️ Potential issue | 🟠 Major

Reset parent editing state when the sidebar unmounts.

If MetadataSidebarRedesign unmounts while a template is being edited, ContentPreview can keep isMetadataEditing=true and a stale modal opener, causing later preview navigation to be blocked against an unmounted sidebar.

Proposed cleanup
     useEffect(() => {
         onEditingStateChange?.(!!editingTemplate);
     }, [editingTemplate, onEditingStateChange]);
 
+    useEffect(() => {
+        return () => {
+            onEditingStateChange?.(false);
+        };
+    }, [onEditingStateChange]);
+
     useEffect(() => {
         setWarningModalOpenCallback?.(handleUnsavedChangesModalOpen);
     }, [setWarningModalOpenCallback, handleUnsavedChangesModalOpen]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
onEditingStateChange?.(!!editingTemplate);
}, [editingTemplate, onEditingStateChange]);
useEffect(() => {
setWarningModalOpenCallback?.(handleUnsavedChangesModalOpen);
}, [setWarningModalOpenCallback, handleUnsavedChangesModalOpen]);
useEffect(() => {
onEditingStateChange?.(!!editingTemplate);
}, [editingTemplate, onEditingStateChange]);
useEffect(() => {
return () => {
onEditingStateChange?.(false);
};
}, [onEditingStateChange]);
useEffect(() => {
setWarningModalOpenCallback?.(handleUnsavedChangesModalOpen);
}, [setWarningModalOpenCallback, handleUnsavedChangesModalOpen]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/elements/content-sidebar/MetadataSidebarRedesign.tsx` around lines 224 -
230, When MetadataSidebarRedesign unmounts it may leave the parent thinking
editing is active and a stale modal opener set; add cleanup to the existing
effects so they reset the parent state and callback on unmount: in the effect
that calls onEditingStateChange (which watches editingTemplate and
onEditingStateChange) return a cleanup that calls onEditingStateChange?.(false),
and in the effect that sets setWarningModalOpenCallback (which depends on
setWarningModalOpenCallback and handleUnsavedChangesModalOpen) return a cleanup
that calls setWarningModalOpenCallback?.(undefined) to clear the stale modal
opener (use the existing symbols: MetadataSidebarRedesign, onEditingStateChange,
setWarningModalOpenCallback, handleUnsavedChangesModalOpen).

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.

2 participants