Skip to content

fix: derive selection geometry from effective scale#1094

Open
jedrazb wants to merge 2 commits into
mainfrom
fix/zoom-aware-layout
Open

fix: derive selection geometry from effective scale#1094
jedrazb wants to merge 2 commits into
mainfrom
fix/zoom-aware-layout

Conversation

@jedrazb

@jedrazb jedrazb commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

The new-comment composer was misplaced at any zoom other than 100% because a page-relative position was scaled twice, and caret/selection geometry ignored a CSS scale applied by a wrapping container. Selection and composer geometry now derive the effective scale from the rendered DOM, so caret, selection rects, and the composer land correctly under both the editor's own zoom and an external scale.

Fixes #1075

Partially addresses #1083 (caret, selection, and composer geometry under an external scale); page-detection and scroll-container sizing under external scale remain open.

🤖 Generated with Claude Code


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

jedrazb and others added 2 commits July 17, 2026 14:27
…1083, fixes #1075)

Two separate causes in one class — mixing post-transform values
(getBoundingClientRect, clientX) with pre-transform ones (offsetWidth,
style.top, the layout model).

#1083: geometry converted screen deltas to layout px by dividing by the
editor's own zoom state. A consumer scaling an ancestor renders the pages
at zoom * externalScale while zoom still reads 1, so the caret landed
hundreds of px off. The scale is now measured off the DOM
(getBoundingClientRect().width / offsetWidth) via getEffectiveScale, so a
scale the editor does not own resolves without the consumer configuring
anything. With no external scale the measurement equals zoom exactly, so
existing behavior is unchanged.

#1075: independent of the above and present at the editor's own zoom. The
composer's fixedY is measured as a client-rect delta, and
resolveItemPositions multiplied it by zoom a second time, placing it
(1 - zoom) * fixedY from its selection. The implementation now matches the
contract its own docstring states. anchorKey values are pagination coords
and keep their scaling; Vue passes zoom 1 here, so it is a no-op there.

Vue's fix is not a copy of React's: its pages carry the scale themselves
while the overlay is their unscaled parent, so the two frames need
different factors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Vue IME candidate window: build the anchor from the raw screen delta plus
  the overlay's screen origin, not overlay-local px added to a screen origin,
  which landed the candidate window ~a third short under external scale.
- Drop the unreachable `|| zoom` fallbacks in readScale / pagesScale /
  toOverlayLocal; getEffectiveScale is always positive-finite. The React hook
  no longer takes a zoom prop it never used. On an unmeasurable container the
  scale is 1, and the comments now say so.
- Soften the changeset to "Fixes #1075; partially addresses #1083" — the diff
  covers caret/selection/composer geometry under scale, not page-detection or
  scroll-container sizing.
- Strengthen two tests: the resolveItemPositions collision test now asserts
  the pushed-down anchor-card position, and the effective-scale e2e imports
  and calls the shipped getEffectiveScale instead of re-deriving the formula.
- Add a Vue e2e assertion on the IME anchor (coordsAtPos lands on the painted
  caret) under external scale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
docx-editor Ready Ready Preview, Comment Jul 17, 2026 3:31pm

Request Review

@eigenpal-release-pal

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅

Posted by the CLA bot.

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.

[Bug] New-comment composer misplaced at zoom ≠ 100%

1 participant