jackwener/maka-agent

fix(ui): keep the prompt rail highlight inside the rail when the rail resizes

オープン

#2,324 opened on 2026/08/06

 (0 件のコメント) (0 件のリアクション) (0 人の担当者)TypeScript (0 件のフォーク)github user discovery
buggood first issue

Repository metrics

Stars
 (1 個のスター)
PR merge metrics
 (PR metrics pending)

説明

What happened

Once the prompt anchor rail is past its cap it becomes a scroller of its own, and PromptAnchorRail keeps the active tick inside that scroller by nudging rail.scrollTop in an effect (packages/ui/src/prompt-anchor-rail.tsx:182). That effect depends on [activeTurnId] only, and does one-shot arithmetic against the railBox/tickBox it measures at that moment.

The rail's own viewport, however, is driven by --maka-prompt-rail-scrollport and --maka-prompt-rail-dock, which a separate ResizeObserver effect (packages/ui/src/prompt-anchor-rail.tsx:148) publishes asynchronously. Any geometry change that lands after activeTurnId settles leaves the correction stale: the active tick — and the indicator anchored to it — is stranded outside the rail's visible box and never comes back, because nothing re-runs the correction until the active prompt changes again.

Observed in a live window: scroll a long transcript to the end, then shrink the window. rail.clientHeight goes 606 → 286, rail.scrollTop stays at 384, and the highlight is outside the rail's box — still there 2s later.

BEFORE        {"railScrollTop":384,"railClientHeight":606,"centreDrift":0,"indicatorInsideRail":true}
AFTER SHRINK  {"railScrollTop":384,"railClientHeight":286,"centreDrift":0,"indicatorInsideRail":false}
LATER (+2s)   {"railScrollTop":384,"railClientHeight":286,"centreDrift":0,"indicatorInsideRail":false}

centreDrift: 0 throughout: the anchor tracking itself is correct. The tick and its highlight are perfectly together — just together in the wrong place.

How to reproduce

  1. Open a conversation long enough that the prompt rail overflows and scrolls internally (~60+ prompts).
  2. Scroll the transcript to the very end, so the last tick is active and the rail has scrolled itself to reach it.
  3. Shrink the window height (or otherwise change the composer dock's height, which feeds the rail's max-height).
  4. The highlight is now outside the rail's visible box and stays there. Scrolling back to another prompt and returning fixes it, because that changes activeTurnId and re-runs the correction.

Where it also shows up: a CI flake

The same defect makes apps/desktop/e2e/prompt-rail.spec.ts:401 (the highlight stays on the active tick while the rail scrolls itself) intermittently fail on CI — run 31082109494, e2e_shard 2/2:

Error: {"railScrollTop":282,"centreDrift":0,"indicatorInsideRail":false}
expect(reading.indicatorInsideRail).toBe(true)

Same signature as above: the correction ran (railScrollTop > 0) against geometry that had not finished settling, and nothing re-ran it. The test's fixed await page.waitForTimeout(600) at line 405 is what decides whether the read lands before or after the last geometry change — it is the exposure, not the cause. Reading the same page at 0/100/300/600/1500/3000ms locally gives six identical results, so waiting longer alone does not make the failing state converge.

Suggested fix

  1. Product: make the correction follow the geometry rather than only activeTurnId — e.g. re-run the same arithmetic from a ResizeObserver on the rail (and its content), or include the measured safe area in the effect's dependencies. Keep the deliberate scrollTop arithmetic rather than scrollIntoView; the comment at packages/ui/src/prompt-anchor-rail.tsx:178 explains why.
  2. Test: replace the fixed waitForTimeout(600) with a condition-based wait (expect.poll over the three readings). Do not relax centreDrift <= 1, and do not just raise the timeout.
  3. Coverage: an e2e assertion that the highlight is still inside the rail after a window resize would lock the product fix.

Environment

  • Maka commit: f7e04f9da
  • OS: macOS (Darwin 25.5.0); the CI failure is Linux
  • Surface: Desktop

コントリビューターガイド