Skip to content

fix(editor): keep focus scopes registered across plugin reconfigurations - #3627

Merged
felipefreitag merged 1 commit into
canaryfrom
fix-focus-scope-registry-wipe-on-reconfigure
Jul 7, 2026
Merged

fix(editor): keep focus scopes registered across plugin reconfigurations#3627
felipefreitag merged 1 commit into
canaryfrom
fix-focus-scope-registry-wipe-on-reconfigure

Conversation

@felipefreitag

@felipefreitag felipefreitag commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

Fixes bubble menus and the Inspector losing the editor selection on click (#3603).

The FocusScopes plugin view wiped its entire scope registry in destroy(). ProseMirror destroys and recreates plugin views on every state reconfiguration, and bubble menus and slash commands register their plugins in mount effects — a reconfiguration that fires right after the EditorFocusScope refs registered the menu/Inspector elements. After mount, only the editor's own view.dom remained registered, so clicking any bubble-menu sub-control or Inspector field was treated as focus leaving the editor: the menu closed, the selection collapsed, and focus went to <body>.

Changes

  • The scope registry now survives reconfigurations. Full cleanup runs only when the plugin is actually removed from the editor state, or when the editor emits destroy.
  • The cleanup intentionally doesn't rely on the if (!editor.isDestroyed) return guard suggested in the issue: ProseMirror destroys plugin views before docView is nulled, so isDestroyed is still false at that point and the guard would make cleanup unreachable (leaking listeners). The editor destroy event covers real teardown instead.
  • Added regression tests: scopes survive a plugin reconfiguration (fails on the previous code), focus tracking stops when the plugin is unregistered, and scope registration is torn down on editor destroy.
  • Added a changeset (patch).

Testing

  • pnpm vitest run --project unit in packages/editor → 496 passed / 1 skipped; tsc --noEmit and biome check clean.
  • Reverting only the source (keeping the tests) makes the new reconfiguration test fail.
  • Manually verified the issue's exact repro on the apps/web full-email-builder example in a real browser: the node-selector dropdown opens and applies without closing the bubble menu, the Inspector keeps the selection while its inputs are focused, and blur to elements outside all scopes still clears the selection as before.

Closes #3603


Summary by cubic

Fixes bubble menus and the Inspector losing the editor selection by keeping focus scopes registered across ProseMirror reconfigurations in @react-email/editor. Selection now stays while interacting with menu/Inspector controls.

  • Bug Fixes
    • Keep the scope registry across reconfigs; only clean up when the plugin is actually removed or the editor is destroyed.
    • Use the editor destroy event for teardown; make register/unregister no-ops after cleanup to prevent re-adding scopes.
    • Add regression tests for reconfig survival, plugin unregistration behavior, and destroy cleanup.

Written for commit 2410fb1. Summary will update on new commits.

Review in cubic

@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-email Ready Ready Preview, Comment Jul 6, 2026 8:24pm
react-email-demo Ready Ready Preview, Comment Jul 6, 2026 8:24pm

@changeset-bot

changeset-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2410fb1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@react-email/editor Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@react-email/editor@3627

commit: 2410fb1

@cubic-dev-ai cubic-dev-ai Bot 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.

No issues found across 3 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

ProseMirror destroys and recreates plugin views on every state
reconfiguration, and bubble menus and slash commands register their
plugins in mount effects. The FocusScopes plugin view wiped the whole
scope registry in destroy(), so right after mount only the editor's own
DOM remained registered and clicking any bubble-menu or Inspector
control blurred the editor and cleared the selection.

The registry now survives reconfigurations; full cleanup runs only when
the plugin is removed from the editor state or the editor is destroyed
(via the editor 'destroy' event, since plugin views are torn down before
isDestroyed flips true).

Closes #3603
@felipefreitag
felipefreitag merged commit d89be14 into canary Jul 7, 2026
18 of 19 checks passed
@felipefreitag
felipefreitag deleted the fix-focus-scope-registry-wipe-on-reconfigure branch July 7, 2026 17:48
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.

Editor: bubble menus & Inspector lose selection on click (FocusScopes wipes scope registry on every reconfiguration)

2 participants