Skip to content

🔲 fix: Anchor Quote Popup to Visible Selection - #16458

Merged
danny-avila merged 3 commits into
devfrom
lia/quote-visible-anchor
Sep 28, 2026
Merged

danny-avila merged 3 commits into
devfrom
lia/quote-visible-anchor

Conversation

@lia-by-librechat

@lia-by-librechat lia-by-librechat Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Selecting part of a long, horizontally scrolling code line can leave “Add to chat” at the far right of the viewport instead of next to the highlighted text. The selection's DOM range includes text hidden outside the code block, so its full bounding rectangle gives the popup a misleading center.

The popup now uses only the selected text visible within the viewport and each fragment’s own clipping ancestors. This keeps later prose visible when a selection starts inside a scrolling code block. The popup follows the visible portion while scrolling and disappears when none of the selection remains visible. The queued quote still contains the selected text, not just its visible slice.

How it works

QuoteButton groups consecutive selected text nodes by clipping context, intersects each group with its own nested scroll containers and the viewport, then positions the popup using their visible union. A single text node retains a fast path. An empty union hides the popup. Focused regressions cover a long code line, scrolling fully out of view, selections crossing code and prose in both directions, and quoting the original selection.

Type of change

  • Bug fix
  • Tests / tooling / CI

Testing

Tested environments/configuration: Client Jest with jsdom and nested scroll-container geometry.

Automated tests:

  • QuoteButton.test.tsx: 8 passed, including wide-code-line and both directions of the cross-container regression.
  • npm run sort-imports -- client/src/components/Chat/Input/QuoteButton.tsx client/src/components/Chat/Input/__tests__/QuoteButton.test.tsx: passed.
  • npm run static-checks: passed on the two staged files (ESLint, Prettier, import order).
  • cd client && npx tsc --noEmit: attempted, but the shared local node_modules resolves stale builds of other workspaces, producing errors in unrelated frontend files. CI should validate against freshly built packages.

Screenshots / recordings

A matching before/after running-app capture was not available locally because no app server is running in this workspace. The reporter's screenshot documents the before state.

Risk / compatibility

No API or stored-data changes. The only behavior change is popup placement and visibility for selections clipped by scroll containers.

Checklist

  • I reviewed my own changes
  • Relevant tests have been added or updated
  • Existing relevant tests pass

@lia-by-librechat

Copy link
Copy Markdown
Contributor Author

Review head 5c04f90: clip the quote popup anchor to the visible selection inside nested scroll containers, with a focused regression for long code lines, sideways scrolling, hidden selections, and preserved quote text.

@danny-avila

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T18:34:46.585615Z 5c04f90 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c04f906af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +189 to +190
for (const clipper of clippers) {
const bounds = clipper.getBoundingClientRect();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Account for selections that leave the starting scroller

When a selection begins inside a code block or table scroller and extends into later prose in the same .message-render, readSelection collects clipping ancestors only from measured.startContainer, but this loop applies all of those rectangles to the bounding box of the entire range. This discards the visible selected prose outside the starting scroller and pins the popup to the code/table instead of the overall visible selection. Clip each range fragment only by ancestors that contain it, or avoid applying the starting node's clippers to a cross-container range.

Useful? React with 👍 / 👎.

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.

Fixed in 8b1fde7. The popup now groups selected text by clipping context, intersects each group with its own scroll ancestors, and merges only visible bounds. Added red-before-green coverage for selections crossing a code scroller and prose in both directions, including scrolling the code fully out of view while retaining the complete quoted text. QuoteButton tests: 8/8; staged ESLint, Prettier, and import-order checks: passed.

@lia-by-librechat

Copy link
Copy Markdown
Contributor Author

Review head 8b1fde7: address the cross-container selection finding by clipping each range group to its own scroller. Regression covers code-first and prose-first selections, scrolling the code out of view, and preserving the complete quote. Focused Jest 8/8; staged static checks passed.

@lia-by-librechat

Copy link
Copy Markdown
Contributor Author

Review head 786dcb1: cross-container selections are clipped per fragment, and text-node traversal is now bounded to the selected range for long messages. Two new red-before-green regressions cover code-first and prose-first selections and preserve the full quote. Focused Jest: 8/8; staged lint, Prettier and import order: passed.

@danny-avila
danny-avila merged commit 5de01de into dev Sep 28, 2026
21 checks passed
@danny-avila
danny-avila deleted the lia/quote-visible-anchor branch September 28, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants