You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Type /page break (or /equation) to insert a block decorator at the start of an empty editor. Lexical inserts a trailing paragraph after the decorator.
Press Backspace once — the trailing paragraph is removed and the decorator becomes a NodeSelection.
Press Backspace again — the decorator is removed; the editor is left with the original empty paragraph at root.
Type any character.
example:
2026-06-12.9.11.56.mov
The current behavior
Step 5 produces a phantom blank line above the typed character. The original empty paragraph is left untouched and a brand-new paragraph is appended after it for the typed text.
Trace: at typing time the RangeSelection's anchor is { key: 'root', offset: 1, type: 'element' }. RangeSelection.insertText routes through $transferStartingElementPointToTextPoint, which lands on the placementNode === null + isRootNode(element) branch (packages/lexical/src/LexicalSelection.ts:295-302). That branch unconditionally appends $createParagraphNode().append(textNode) to root, so the empty paragraph already at root is left behind.
The expected behavior
The typed character should land in the existing empty paragraph (the natural caret target after the decorator delete), with no extra blank line.
Impact of fix
Affects every block decorator that root can host (PageBreak, Equation, HorizontalRule, custom Card / Figure decorators, …).
One-line guard in $transferStartingElementPointToTextPoint: when root's last child is an empty non-inline ElementNode, reuse it instead of appending a new paragraph. PR coming up.
Lexical version: latest on playground.lexical.dev (also reproducible against current main)
Steps To Reproduce
/page break(or/equation) to insert a block decorator at the start of an empty editor. Lexical inserts a trailing paragraph after the decorator.example:
2026-06-12.9.11.56.mov
The current behavior
Step 5 produces a phantom blank line above the typed character. The original empty paragraph is left untouched and a brand-new paragraph is appended after it for the typed text.
Trace: at typing time the RangeSelection's anchor is
{ key: 'root', offset: 1, type: 'element' }.RangeSelection.insertTextroutes through$transferStartingElementPointToTextPoint, which lands on theplacementNode === null + isRootNode(element)branch (packages/lexical/src/LexicalSelection.ts:295-302). That branch unconditionally appends$createParagraphNode().append(textNode)to root, so the empty paragraph already at root is left behind.The expected behavior
The typed character should land in the existing empty paragraph (the natural caret target after the decorator delete), with no extra blank line.
Impact of fix
$transferStartingElementPointToTextPoint: when root's last child is an empty non-inline ElementNode, reuse it instead of appending a new paragraph. PR coming up.