I made a quick test plugin and it logs out the expected positions - they’re just not being set. I don’t really know what to make of the issue. What’s more - it only affects our editor when it’s nested in our app and not otherwise - but I already stripped away virtually everything about our app from the DOM to the CSS and the issue persists.
Conditions for reproduction:
white-space: pre
Horizontal scrollbar enabled on codeBlock
Some unknown secret sauce
I wonder if anyone has any ideas what could be the cause of this very strange bug?
I tried poking around in the mousedown handler in prosemirror-view but I couldn’t find anything going wrong there either. Everything looks correct to me, except in the end the selection is not set.
Reverting to white-space: pre-wrap “fixes” it, and more interestingly, dragging the mouse 1px before lifting the mouse button correctly sets the position in the editor, even though plain clicking does not.
I know this seems like a non-issue or project-specific problem, but I do believe there’s something a bit more generalizable going on here.
I’ve spent about 3 entire workdays on this now and ruled out literally everything I can conceive of. Even when the editor is the sole DOM element (besides its contents) this issue persists. I upgraded our Electron version to match the working Chromium version, but still in Electron ProseMirror exhibits this inability to click inside of the codeBlock. Like I said, the mousedown in a plugin yields the correct pos in the editor, but it’s not set, so I really cannot fathom what’s wrong.
After much investigation, it certainly seems to be an issue with ProseMirror to me, however idiosyncratic its presentation.
If I set a expanded selection in a non-problem area and then drag into the problem codeblock in a separate click, instead of selecting only the text in the codeblock, it expands the original selection into the codeblock, which to me is more evidence something is going awry in ProseMirror here.
I removed all non-browser CSS except the white-space and overflow-x styles necessary to provoke the bug. I remove the entire DOM except the editor and the full HTML on the page is like below - but still the issue persists. No issue in Chrome 124.0.6367.201, but the problem persists in Electron 30.0.6, which is based on Chromium 124.0.6367.207 - and it also affected all previous Electron versions. It’s utterly baffling.
Styles (besides browser and prosemirror-view’s included styles):
pre {
overflow-x: auto;
}
pre, pre code {
white-space: pre;
}
I’d be happy to try to trace down what’s failing in ProseMirror itself if I had any idea where to begin. Everything looks fine to me, but it’s not like I really know what the workflow is supposed to be.
@marijn I finally pared my app down enough to run it directly in the browser. The browser exhibits no problems, yet in Electron we cannot select inside the codeblock still with a singleClick. There must be a bug somewhere, but I haven’t enough of a clue where to track it down and file a meaningful bug report.
Are there any hints you can provide?
I apologize for the lengthy explanations above; I don’t know how else to more succinctly articulate this strangest of issues.
PS: My example above uses TipTap’s React NodeView renderer, but the issue occurs even if we use a plain NodeView or register no NodeView.
This does sound very much like browser misbehavior. Often the only way around stuff like this is to change your setup to avoid the bug, and hope the browser eventually fixes it.
I haven’t much experience reporting browser bugs, and certainly not highly esoteric ones. I wonder if you have any advice for how I might try to get this properly reported and resolved.
For example, it’s not present in Chrome, so I guess I shouldn’t be considering this a Chromium bug? So then I should be talking to the Electron team instead? Or do you think it’s still possible this is actually in Chromium somehow?
Sorry I know this is outside the scope of the forums now, but if you have any advice I’d value it greatly.
Since older version off Electron are insecure I seem quite stuck on this. I could try to re-implement ProseMirror’s handling of cursor selections, and I have tried, but that’s proved quite difficult to handle the edge cases.
Is there anywhere you might suspect prosemirror-view code could be failing that I could investigate further? The fact that ProseMirror can detect the clicked coordinate is so very strange.
@marijn thank you again for your help with this. The root cause has been identified and it seems that some changes may be necessary to ProseMirror (or TipTap, or at least by end developers of these packages) to accommodate upcoming Chromium accessibility changes. https://issues.chromium.org/issues/342705690#comment31
As a quick refresher: The issue is that horizontally scrolling pre elements cannot be clicked to focus the intended position in the editor.
When I try this with Chrome 124 with --enable-features=KeyboardFocusableScrollers, I’m only getting focus on the <pre> when I click directly on the scrollbar. Clicks on the text work as expected. If this requires the precise behavior of your pluging to cause issues, I think you’re going to have to adjust your plugin, and it’s not something ProseMirror’s core is going to try and work around.
The included FocusExtension is a crucial part of reproducing this issue. It just adds a decoration to the focused line. Its code can be seen here .Together with KeyboardFocusableScrollers, this breaks focusing the scroller.
I’m hopeful Chromium devs might be able to resolve this, but if they cannot, I do believe this is something ProseMirror should address internally.
I understand you may view this as the responsibility of the end-developer, but I already tried for days to work around this without success and I expect we will not be the only ones affected, but merely the first because we control the environment and have experimental features enabled which will soon land in stable Chrome.
So it seems as though these changes started rolling out more widely in Chrome this week and we’ve started getting similar reports of horizontally scrollable elements being completely unusable – I am confident that this is:
a) A chromium bug (Disabling the chrome flag “keyboard focusable scrollers” fixes the issue)
This is not a Chromium bug (and so will never be fixed on the Chromium side.) This is ProseMirror not handling an extenuating circumstance Chromium’s new accessibility feature has created.
Perhaps, one thing I noted in testing is that if you add a breakpoint on the global click handler and then click into the scrollable container nothing is triggered. It doesn’t pause the code at all – so it’s like chrome is never even allowing the click handling code to execute.
It looks like pointerdown is firing and ProseMirror is handling it somehow, so I take that back
This polyfilled the behavior of :focus-visible state when it was less supported a couple of years ago by adding a class to keyboard focused elements. Now that there is broad support it can be removed.
It’s easy to see how the Chrome change + that module + ProseMirror watching DOM modifications would cause a conflict here.
Hi! I am the chromium engineer working on shipping the new feature KeyboardFocusableScrollers. This new feature is shipping in Chrome 127 and will be enabled for users at 100% in the upcoming week. We have had a few report of breakages for ProseMirror users, hence I am writing here to clarify what the feature does.
This feature introduces the following changes:
Scrollers are click-focusable and programmatically-focusable.
Scrollers without focusable children are keyboard-focusable by default. They can be opt out of keyboard focus by setting a negative tabindex.
This is an important improvement to help make scrollers and contents within scrollers more accessible to all users. We have had accessibility users requesting this change for years and some future web capabilities improvements depend on it. You can read more about its benefits in the post here: Focusseerbare scrollers op het toetsenbord | Blog | Chrome for Developers.
We have landed Origin Trial and an enterprise flag to help web sites opt out of the behavior temporally while they update their focus logic.
ProseMirror is a great tool and I do apologize for the inconvenience of having to update existing logic.
I hope this can be fixed. All the kings horses and all the chromium devs could not find a workaround so far. There’s no polyfill we can remove to resolve our issue, so we’ll be dead in the water when the flag to disable keyboard focusable scrollers goes away.
We would like to update this issue and say we have disabled the feature in the current Chrome version 127. After multiple feedbacks and discussion with the team, we have decided to modify the existing feature to not make scrollers mouse focusable. This should fix the bug reported by OP here. While this gets fixed, the feature is disabled.
The plan is still to allow scrollers to be keyboardfocusable by default and we hope to re-launch the feature with the fix in the upcoming months. You can find more information on our response here:
https://issues.chromium.org/issues/361072782#comment7