Skip to content

Conversation

@iamakulov
Copy link
Contributor

@iamakulov iamakulov commented Jan 8, 2026

When CodeMirror is the first element in ProseMirror, and you press Cmd+A in ProseMirror, the selection doesn’t get applied (or, rather, applies for a single frame). Instead, the CodeMirror element steals the focus.

Repro: CodeSandbox, demo:

CleanShot.2026-01-08.at.20.23.32.mp4

Cause: This seems to boil down to an interaction between ProseMirror’s selection logic and CodeMirror being contenteditable itself. When ProseMirror handles a Cmd+A event, it calls domSel.collapse() before calling domSel.expand():

https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L464-L468

  • domSel.collapse() makes the selection collapse to a single point – at the beginning of the editor
  • The element at the beginning of the editor is CodeMirror – so when that happens, the browser triggers the native focus event on it.
  • This, in turn, triggers CodeMirror’s focus handling, causing it to steal the focus from ProseMirror after the 10ms timer fires.

Solution: This PR attempts to fix the issue. The fix seems to work, but maybe there’s a better place for it, or some edge cases I don’t know about (I’m not very familiar with contenteditable gotchas).

@iamakulov iamakulov changed the title Fix a selection issue where the CodeMirror is the first element in Pr… Fix a selection issue where the CodeMirror is the first element in ProseMirror Jan 8, 2026
@iamakulov
Copy link
Contributor Author

iamakulov commented Jan 8, 2026

(You can test this in CodeSandbox by swapping the @codemirror/view import with @iamakulov/codemirror-view.)

@iamakulov
Copy link
Contributor Author

(The issue seems to be Chromium-only, btw.)

@iamakulov
Copy link
Contributor Author

(And it seems to be new: in BrowserStack, I can only repro it starting Chrome 135+. Could be a browser bug, after all!)

@iamakulov
Copy link
Contributor Author

Filed upstream: https://issues.chromium.org/issues/474377386. Thank you for being my rubber duck :D Let’s see what Chromium responds.

@marijnh
Copy link
Member

marijnh commented Jan 9, 2026

I find this patch somewhat scary. It is entirely possible for an editor to receive focus while the selection is elsewhere in the document, and this would cause the library to ignore such focus events entirely, allowing focus-tracking code to get confused.

It seems possible to work around this problem by adding any kind of inline element in front of the inner editor. Would adding a kludge like <div style="position: absolute" aria-hidden=true>&#8203;</div> to the start of your CodeMirror node view work for you? It's not a general fix, but it's also less likely to cause additional issues.

@iamakulov
Copy link
Contributor Author

Oh, that’s clever!

That seems to solve Cmd+A (CodeSandbox), but it actually does cause more issues haha. With this workaround, Safari stops showing the Cmd+A highlight at all, and in both Chrome and Firefox, pressing gets the cursor stuck in the zero-width space div:

CleanShot.2026-01-09.at.15.44.04.mp4

You can work around that by also adding a contenteditable="true" on the div with the zero-width space. It’s still not great, tho (it leads to an extra cursor position in front of the code editor, and to Safari highlighting the whole page on Cmd+A). Meh :/


Another thing I noticed: having CodeMirror first in ProseMirror also seems to break Cmd+C? (LMK if you’d like me to raise a separate issue for this.)

For example, in the original demo, if you Cmd+A in Safari (which works) and then Cmd+C, the only thing the browser copies is // This CodeMirror block is first instead of the whole text. Chrome (with this PR’s fix) has a similar issue. (Firefox works fine.)

The zero-width div workaround that you suggested solves it, but at the cost of the above issues.

@iamakulov
Copy link
Contributor Author

Another thing I noticed: having CodeMirror first in ProseMirror also seems to break Cmd+C? (LMK if you’d like me to raise a separate issue for this.)

Filed a fix for that: #79

@marijnh
Copy link
Member

marijnh commented Jan 13, 2026

With this workaround, Safari stops showing the Cmd+A highlight at all, and in both Chrome and Firefox, pressing ↑ gets the cursor stuck in the zero-width space div

Ughhh, you're right. Nesting editable elements is a space where browsers do some really bizarre things.

I'm still worried that the fix is worse than the problem here. Even if we ignore that focus event, it seems the browser does put the actual focus on the inner editor, which is clearly not what you want. So maybe a kludge in ProseMirror that detects this situation right after selecting all, and forces the focus back to itself, is a more promising direction.

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