Skip to content

[lexical-playground] Bug Fix: Position FloatingLinkEditor below the entire link for multi-line and decorator-only links#8419

Merged
etrepum merged 1 commit intofacebook:mainfrom
mayrang:fix/floating-link-editor-multiline
Apr 30, 2026
Merged

[lexical-playground] Bug Fix: Position FloatingLinkEditor below the entire link for multi-line and decorator-only links#8419
etrepum merged 1 commit intofacebook:mainfrom
mayrang:fix/floating-link-editor-multiline

Conversation

@mayrang
Copy link
Copy Markdown
Contributor

@mayrang mayrang commented Apr 29, 2026

Summary

  • Fixes Bug: Link editor is mispositioned when link is multiple lines tall #8263. For multi-line links, the floating link toolbar attached to the cursor's range rect (one line tall), so a cursor on line 1 placed the toolbar between line 1 and line 2 — covering line 2 (and the cursor when it sat there).
  • The NodeSelection branch already uses the link element's bounding rect; align RangeSelection by looking up the LinkNode and using getClientRects()[last] (the last visual line of the link). Falls back to the prior range-rect behavior when the cursor is not inside a link.
  • For decorator-only links (e.g. an image wrapped in a link), the link element's line box can be misaligned with the decorator's visual extent (baseline-based positioning makes the <a> rect sit on the image's lower half). When the link has a single decorator child, anchor to the decorator's rect directly so the toolbar lands below the image.

Before

스크린샷 2026-04-30 오전 1 51 52

After

스크린샷 2026-04-30 오전 1 52 23

Test plan

  • Single-line link: toolbar appears below the link (no regression)
  • Multi-line link, cursor on line 1: toolbar appears below the last line, not covering line 2
  • Multi-line link, cursor on line 2: toolbar appears below the last line
  • Image link (decorator-only link): toolbar appears below the image
  • Single-character link ([lexical-playground] Bug Fix: Show floating link editor for single-character links #8392): still works via $getSelectedLinkNode's right-bias path

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lexical Ready Ready Preview, Comment Apr 30, 2026 3:39pm
lexical-playground Ready Ready Preview, Comment Apr 30, 2026 3:39pm

Request Review

if (linkElement) {
const rects = linkElement.getClientRects();
domRect =
rects[rects.length - 1] ||
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It looks like floating-ui has a better solution for this sort of situation. https://floating-ui.com/docs/inline

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing to inline! I tried it and ran into an issue I couldn't resolve cleanly.

After applying inline, the toolbar lands at different visual positions across attempts even when the reference is the same.

Attempt A:
image
image

Attempt B:
image

image

Hello(link: www.google-)
Bye(link: www.naver-)

Both attempts log the same reference:

  • text: bye
  • rect: {top: 298.27, left: 28, width: 98.33, height: 17.5}

Same reference, identical rect, different rendered position. The same pattern reproduces with another link in the document. Calling update() explicitly after setReference() did not change the outcome.

For this PR, I kept the single bounding rect approach (linkElement.getBoundingClientRect()) since the issue doesn't reproduce there.

The behavior with inline looks like it needs a deeper look — would you prefer to investigate it in this PR, or split it into a separate issue and look into it there? Happy to either way.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Slight preference to try and resolve all known positioning issues with the floating link toolbar in this PR, but up to you

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Dug into this more — turned out it's how setReference(domElement) interacts with inline, not inline itself. Swapped it for setPositionReference with a virtual element exposing both rect methods, and the positioning issues went away. Updating the PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Pushed the change. Switched to setPositionReference with a virtual element exposing both getBoundingClientRect() and getClientRects(), and inline is now in the middleware chain. Verified the previously broken cases (viewport-bottom flip, mouse vs keyboard entry, sticky placement) all behave correctly with this approach.

…ast line of multi-line links

For multi-line links, the toolbar attached to the cursor's range rect
(one line tall), so a cursor on line 1 placed the toolbar between line 1
and line 2 — covering line 2. Use the link element's last client rect
(the last visual line of the link) as the reference for floating-ui so
the toolbar always sits below the entire link. Falls back to the range
rect when the cursor is not inside a link.

Fixes facebook#8263
Copy link
Copy Markdown
Collaborator

@etrepum etrepum left a comment

Choose a reason for hiding this comment

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

Looks great for the cases I tried!

@etrepum etrepum added this pull request to the merge queue Apr 30, 2026
Merged via the queue into facebook:main with commit c895aad Apr 30, 2026
44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. extended-tests Run extended e2e tests on a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Link editor is mispositioned when link is multiple lines tall

2 participants