Skip to content

[COMMS-806] Documents: impossible to delete characters with backspace after adding a wp link#169

Open
judithroth wants to merge 2 commits into
devfrom
jr/bug/stc-806-documents-impossible-to-delete-characters-with-backspace-after-adding-a-wp-link
Open

[COMMS-806] Documents: impossible to delete characters with backspace after adding a wp link#169
judithroth wants to merge 2 commits into
devfrom
jr/bug/stc-806-documents-impossible-to-delete-characters-with-backspace-after-adding-a-wp-link

Conversation

@judithroth

Copy link
Copy Markdown
Contributor

Ticket

https://community.openproject.org/wp/COMMS-806

SO FAR THIS IS JUST A PROOF OF CONCEPT - the cursor placement needs to be refined, but overall it's having the expected effect to make backspace work again.

What are you trying to accomplish?

Screenshots

What approach did you choose and why?

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

wrong cursor placement when inserting in the middle of a text
Copilot AI review requested due to automatic review settings June 26, 2026 10:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR is a proof-of-concept mitigation for a regression where Backspace stops deleting text after inserting an inline work package link (“WP chip”), by forcing an additional cursor placement step to trigger ProseMirror/Yjs re-sync.

Changes:

  • Adds an extra cursor placement (setTextCursorPosition(..., 'end')) after inline WP insertion in the SlashMenu and HashMenu flows.
  • Refactors formatting for placeCursorAfterInlineNode usage/signature.
  • Touches the cursor-position integration test file (currently only via imports).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
test/lib/components/integration/editor.cursorPosition.browser.test.tsx Adds editor helper imports (currently unused).
lib/utils/cursor.ts Reformats placeCursorAfterInlineNode signature for readability.
lib/components/SlashMenu.tsx After inline WP insertion, forces an additional cursor placement to try to restore Backspace behavior.
lib/components/HashMenu/editorUtils.ts After hash-menu chip insertion, adds a BlockNote cursor placement attempt intended to land after trailing space / trigger re-sync.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +4 to +7
import {
insertInlineWorkPackageViaHash,
insertInlineWorkPackageViaSlashMenu,
} from '../../../helpers/editorHelpers';
//
// A re-sync event (timeout, click, or next edit) restores normal behavior.
// We're setting the cursor position to trigger this re-sync event.
editor.setTextCursorPosition(current.blockId, 'end');
Comment on lines +67 to 73
// Additionally place the cursor via the BlockNote API. When the chip (plus its trailing
// space) is the last content of the block, setTextCursorPosition('end') lands the cursor
// after the trailing space; it runs after placeCursorAfterInlineNode so it wins. Mid-block
// we keep placeCursorAfterInlineNode's position, since BlockNote has no inline-offset API.
const blockId = editor.getTextCursorPosition()?.block?.id;
editor.setTextCursorPosition(blockId, 'end');
});
Comment on lines +63 to +65
// Mitigate bug where backspace would not work on text typed directly after adding
// a new inline work package link.
// Tiptap's built-in Backspace handler only covers special cases - undoing input
@ihordubas99

Copy link
Copy Markdown
Collaborator

The ideal fix would be to place the cursor right after the chip (not at end-of-line) so the user can immediately type at the correct position. All attempts to do this while keeping Backspace functional failed:

Attempt 1 - placeCursorAfterInlineNode at range.to (between chip and trailing space)
Backspace stops working. When the user types after the chip, text lands adjacent to the atom node. ProseMirror's domObserver (MutationObserver) misreads DOM mutations near contenteditable="false" boundaries - it produces no tr.delete() transaction and the deletion is silently lost.

Attempt 2 - placeCursorAfterInlineNode at range.to + 1 (after the trailing space, same absolute position as setTextCursorPosition('end') for end-of-block chips)
Same result. Even though the position is mathematically identical to what setTextCursorPosition produces, dispatching it via editor.transact(tr.setSelection(...)) does not reproduce the effect. The domObserver issue persists.

Attempt 3 - setTextCursorPosition('end') first, then placeCursorAfterInlineNode
Theory: trigger the re-sync via setTextCursorPosition, then reposition to after the chip. Calling placeCursorAfterInlineNode afterwards immediately reintroduces the bug - the re-sync is not durable.

Attempt 4 - synthetic arrow key events
Dispatched ArrowRight + ArrowLeft KeyboardEvents on view.dom to force a domObserver flush. No effect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants