Skip to content

fix(liturgy): alignment arrow recompute from live DOM on hover#64

Open
anantham wants to merge 1 commit into
mainfrom
fix/opus-alignment-arrow-stale
Open

fix(liturgy): alignment arrow recompute from live DOM on hover#64
anantham wants to merge 1 commit into
mainfrom
fix/opus-alignment-arrow-stale

Conversation

@anantham
Copy link
Copy Markdown
Owner

Bug

After switching script (IAST ↔ Devanāgarī) on a chant like /liturgy/bodhi-sangha/ti-sarana, the hover alignment arrow could land at negative coordinates (e.g. start at M -24,-203) instead of the actual word position. The arc end (English) was correct; only the source-side endpoint was stale.

Root cause

computeAlignmentLines runs in a useLayoutEffect keyed on activeScript.lang. When the script swap fired, the new-script spans (Devanāgarī) had zero size momentarily — Noto Serif Devanagari hadn't loaded yet, or the layout hadn't settled. wordRect.bottom = 0 produced negative coordinates relative to cRect.top. These bad values stuck in the lines state.

The hover-time adjustment in adjustedLines only patched ONE endpoint (the hovered one). The other end kept the stale cached value.

Fix

On hover, recompute the alignment lines fresh from live DOM. By the time the user is hovering, the DOM has settled. Costs one extra DOM measurement per render-during-hover, which is bounded by hover duration.

The non-hover branch is unchanged (still returns cached lines), and lines never paint when not hovered anyway — AlignmentLines filters by hover.

Verification

  • IAST hover Dhammaṁ → arrow at (127, 49)
  • Switch to Deva, hover धम्मं → arrow at (164, 49) ✓ (was (-24, -203))
  • Switch back to IAST, hover Dhammaṁ → arrow at (127, 49)
  • 284 alignment-audit tests pass (32 skipped pre-existing)
  • Tested at /liturgy/bodhi-sangha/ti-sarana

🤖 Generated with Claude Code

The hover arrow could land at negative coordinates (off-screen / wrong
position) after switching script (IAST ↔ Devanāgarī). Root cause: the
`lines` state was populated by computeAlignmentLines during a transient
layout — e.g. just after the script swap, before Noto Serif Devanagari
fonts loaded — when the new-script word spans had zero size. Cached
endpoints had `wordRect.bottom - cRect.top` = (0 - 203) = -203.

The hover-time adjustment only patched the Pāli endpoint (when hovering
Pāli) or the English endpoint (when hovering English) — it trusted the
cache for the other end, so the bad value survived.

Fix: in `adjustedLines`, recompute fresh from live DOM whenever there's
a hover. By that point the DOM is settled and rects are accurate. The
hover-only branch keeps the cost bounded — non-hovered renders still
return the cached `lines` (which never paint anyway since AlignmentLines
filters by hover).

Verified: switching IAST→Deva→IAST and hovering Dhammaṁ / धम्मं in
each direction now produces correctly-anchored arrows (164,49) and
(127,49) instead of (-24,-203). All 284 alignment-audit tests pass.

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

vercel Bot commented May 17, 2026

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

Project Deployment Actions Updated (UTC)
lexicon-forge Ready Ready Preview, Comment May 17, 2026 1:57am

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.

1 participant