fix(chat): anchored-scroll behavior parity with the reference model
Six reported defects, one root theme — our port diverged from the reference semantics: - a user gesture no longer collapses the reserved anchored end space (that snap-to-bottom was the 'anchoring vanishes on a micro-scroll'); it only disarms the follow/anchor machinery, and anchor remeasures after the user takes over can no longer re-position the viewport - the anchor arms synchronously BEFORE the send reaches the store, and the claim compares against the arm-time baseline — arming a frame after the optimistic row committed is why anchoring 'rarely worked' and sending from mid-history did nothing - gestures are selective (wheel up, touch/pointer away from the end, PageUp/Home/ArrowUp), so scrolling toward the end or clicking a row at the live edge no longer kills follow - 'at end' is a tight 40px band against the full content length instead of the list's half-viewport isNearEnd, so the scroll-to-bottom pill appears when the viewport actually leaves the end - reaching the end re-arms follow without knocking an anchored turn out of its mode, and the overlay scrollbar suppression follows scroll ownership rather than the anchor's mere existence - the status/working row moved out of the list footer to a fixed spot above the composer: inside the list it walked down with every streamed line, and its unmount was part of the end-of-stream jerk
This commit is contained in:
@@ -361,10 +361,6 @@ const ChatViewport = React.memo(({
|
||||
|
||||
<SessionRecapNote sessionId={currentSessionId} directory={directory} isMobile={isMobile} />
|
||||
|
||||
<div className="mb-3">
|
||||
<StatusRowContainer />
|
||||
</div>
|
||||
|
||||
<div className="flex-shrink-0" style={{ height: isMobile ? '40px' : '10vh' }} aria-hidden="true" />
|
||||
</>
|
||||
), [currentSessionId, directory, isMobile, sessionPermissions, sessionQuestions]);
|
||||
@@ -417,6 +413,13 @@ const ChatViewport = React.memo(({
|
||||
scrollContainerProps={scrollContainerProps}
|
||||
/>
|
||||
<OverlayScrollbar containerRef={scrollRef} suppressVisibility={isProgrammaticFollowActive} userIntentOnly observeMutations={false} />
|
||||
{/* Static above the composer: inside the list it walked down
|
||||
with every streamed line while a turn was anchored. */}
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-2 z-10">
|
||||
<div className="pointer-events-auto [&:not(:has(*))]:hidden">
|
||||
<StatusRowContainer />
|
||||
</div>
|
||||
</div>
|
||||
{showPromptNavigator && promptTurnIds.length >= 2 ? (
|
||||
<PromptNavigatorRail
|
||||
turnIds={promptTurnIds}
|
||||
|
||||
Reference in New Issue
Block a user