Cursor stays after placeholder, gives impression like placeholder is the text

Given an editor already has focus (like after clicking it with LMB),
when clicking RMB on the placeholder,
the cursor is displayed at the end of the placeholder.

It’s reproducible on my machine with minimal code:

import {EditorState} from "@codemirror/state"
import {EditorView, placeholder} from '@codemirror/view';

new EditorView({
  doc: "",
  extensions: [
    placeholder('any text')
  ],
  parent: document.body
})

I also ran it in: Try CodeMirror and got the same result.

Clicking with RMB always reproduces this issue for me, but my users report that occasionally it happens on their mobile devices, and when that happens, they can’t type. I wasn’t able to reproduce that though.

Using drawSelection (or basicSetup) avoids this. I’m not sure it is possible for the library to change the native cursor position at the precise moment when the context menu pops up.

2 Likes

thanks for a quick answer, I really appreciate it!

Quick question, @marijn, what would be the best way to write a test for that? I mean, how to write assertion that drawSelection() was used? I’m thinking creating EditorView and EditorState in test, and somehow inspecting dom maybe?

What dom inspection is the least likely to change in your opinion, safe enough to write a unit test for it?

If there is a .cm-selectionLayer DOM node in the editor, drawSelection is enabled.

1 Like

One more question @marijn. What would be the best way to change the colour of the drawn cursor based on theme?

I change the theme of the editor to light or dark theme, and when I have dark theme, then the black cursor is barely visible.

Are you marking your theme as dark? Then the cursor should be grey. Though I just noticed that the default dark theme cursor color (#444) might actually still be too dark. Is that what you’re seeing?

Yes, I’m seeing a cursor of color #444. My background is #1A1A1A.

Attached patch makes this default color a bunch lighter. (But it’s often a good idea for themes to define their own cursor color that fits the background color.)

1 Like

@marijn In android, the cursor appears at the placeholder even with drawSelection() enabled :confused:

@marijn When I enabled drawSelection(), then the selection appears below Decoration.line() if I set background-color for the line decoration, the effect is wierd.

Is there some way to display decoration line background below, then the selection background, and then the content of the line?

Maybe there is a simpler way to fix this wierd cursor at placeholder quirk? :thinking:

PS: For that matter, any kind of styling (Decoration.mark()) and regular styling using css or EditorView.baseTheme() with background-color is above the selection :confused:

Decoration.line adds attributes to the line element that wraps the text. As such, I have no idea how the selection can appear below the decoration, since the decoration itself takes up no space.

Maybe you are looking for a block widget decoration?

1 Like

@marijn What I mean, is that with system selection, if the element itself has background, the selection is seen above it (when I say “above” I mean it has a higher z-index).

Like this (system selection):

image

With drawSelection(), if the element has background, regardless of whether its from styling, baseTheme(), Decoration.mark() or Decoration.line(), then the background is higher, and the drawn selection is always below (when I say “below” I mean it has a lower z-index and is obscured by the background), like so:

image

When I select text only inside the background, then I can’t see the selection at all:

image

Nonetheless, my main issue is the cursor quirk with placeholder and context menu from the topic. Maybe there’s a simpler way to fix it, other than drawSelection()?

Maybe the placeholder extension can be updated to render text using css pseudo-element? :thinking: Maybe then browser wouldn’t place the cursor at the end of it at the context menu open.

Making the background transparent can help, but yes, background styling works poorly with the selection, and you should try to avoid it.