Repository navigation
fix(inline-toolbar): make tool shortcuts work with several Editors on a page - #3048
Open
playlikeboy wants to merge 4 commits into
Open
playlikeboy wants to merge 4 commits into
playlikeboy wants to merge 4 commits into
Conversation
playlikeboy
requested review from
TatianaFomina,
gohabereg,
ilyamore88 and
neSpecc
as code owners
November 13, 2026 18:06
Inline Tools shortcuts are bound to the document so they work in read-only mode, but they were stored in the page-wide Shortcuts registry, which allows one handler per shortcut and element. The second Editor on a page failed to register its shortcuts (the error was swallowed), so CMD+B and others did nothing there. The same happened to an Editor created after another one was destroyed, because close() removed the shortcuts from the redactor, where they were never bound, and destroy() did not remove them at all. Each Inline Toolbar now keeps its own shortcuts, handles one only when the selection is inside its Editor, and removes them on destroy. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Follow the pattern of the Link tool tests: select the text, give the Inline Toolbar time to open and register its shortcuts, then press the shortcut. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The destroy/recreate test does not verify document-listener cleanup, so it can pass even when leaked handlers retain destroyed Editors.
1 open issue
What changed in this PR
Fixes #3002 by giving each Editor its own inline-tool shortcut handlers, avoiding conflicts between instances while preserving document-level binding for read-only support.
Changes:
- Registers shortcuts per Editor, scopes handling to its selection, and removes handlers on destruction.
- Adds regression tests for multiple Editors and destroy/recreate behavior.
- Documents the fix and bumps the package to
2.32.0-rc.4.
| File | Description |
|---|---|
test/cypress/tests/modules/InlineToolbar.cy.ts |
Adds multi-instance and destroy/recreate shortcut tests. |
src/components/modules/toolbar/inline.ts |
Manages per-Editor shortcuts, selection checks, and cleanup. |
package.json |
Bumps the release candidate version. |
docs/CHANGELOG.md |
Records the inline shortcut fix. |
Review effort: Balanced
Comment on lines
+152
to
+153
| this.registeredShortcuts.forEach((shortcut) => shortcut.remove()); | ||
| this.registeredShortcuts.clear(); |
Contributor
Author
There was a problem hiding this comment.
Added in 03f4e91: the new test records the keydown listeners bound to the document, checks that opening the Inline Toolbar adds some, and expects none to be left after destroy(). With the two cleanup lines removed, three listeners stay bound, so the test fails without them.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…rom the document Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This branch has not been deployed
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.

Summary
Fixes #3002. With two Editors on a page, Inline Tools shortcuts (
CMD+B,CMD+I, ...) only work in the Editor whose Inline Toolbar opened first. The same happens to an Editor created after another one was destroyed.Root cause
Since #2832 the shortcuts are bound to
document(needed for read-only mode), but they are still stored in the page-wideShortcutsregistry, which allows one handler per shortcut name and element:Shortcuts.add()throws "already registered". Thetry/catcharoundenableShortcuts()swallows it, so its shortcuts are never bound. The first Editor's handler runs, but its popover is closed, so nothing happens.close()callsShortcuts.remove(redactor, shortcut), but the shortcut is bound todocument, so it is never removed.destroy()does not remove it either, so the handler of a destroyed Editor stays on the document and blocks every Editor created later.Changes
src/components/modules/toolbar/inline.tsShortcutinstances (still ondocument), registers each once, and removes them indestroy().Shortcuts.remove(redactor, ...)call fromclose(). It never matched an inline shortcut, and it could remove a Block Tool shortcut with the same name that the Toolbox bound to the redactor.try/catch, which is no longer needed.test/cypress/tests/modules/InlineToolbar.cy.ts: two tests (two Editors on a page; an Editor created after another one was destroyed).docs/CHANGELOG.mdline andpackage.jsonbumped to2.32.0-rc.4(same as fix(sanitizer): merge sanitize rules for the same tag instead of overwriting them #3041; I'll re-bump whichever of the two lands second).Testing
eslinton the changed files: no errors.vite buildin production and test mode: passes.nextCMD+Bin the 2nd Editor on the page<b>Second</b> editor textCMD+Bin an Editor created after the first was destroyed<b>Second</b> editor textNote:
tscreports the missing type declaration for@codexteam/shortcutson the new import, the same as it already does forutils/shortcuts.ts.🤖 Generated with Claude Code