refactor(chat): share composer, scroll follow and jump control across both chat surfaces
The rectification session rendered its own textarea (no length ceiling, no count), its own rAF scroll follow with a sticky-scroll helper, and its own jump chip styled differently from the main chat's inline Tailwind button, while the main chat re-ran scrollTo on every streamed token and added a smooth scroll on settle. ChatComposer now accepts a controlled value so the rectification surface reuses it without touching the main draft store; useConversationScrollAnchor owns the follow through a ResizeObserver, one frame per content change, for both surfaces; a single JumpToLatestButton replaces both chips; the 720px transcript override is gone. DESIGN.md records the shared composer, the jump control, the reading width and the two shadow tokens. BUG-477 BUG-478 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* Sticky follow for a streaming message viewport.
|
||||
*
|
||||
* Auto-follow only when the user is already near the bottom. Streaming
|
||||
* updates must not steal scrollTop after the user moves upward.
|
||||
*/
|
||||
|
||||
export const RECTIFICATION_NEAR_BOTTOM_PX = 96;
|
||||
/** Keep the jump chip hidden while a choice card still occupies the composer overlay band. */
|
||||
export const RECTIFICATION_CHOICE_NEAR_BOTTOM_PX = 360;
|
||||
|
||||
export function distanceFromBottom(
|
||||
scrollHeight: number,
|
||||
scrollTop: number,
|
||||
clientHeight: number,
|
||||
): number {
|
||||
return scrollHeight - scrollTop - clientHeight;
|
||||
}
|
||||
|
||||
export function isNearBottom(
|
||||
scrollHeight: number,
|
||||
scrollTop: number,
|
||||
clientHeight: number,
|
||||
thresholdPx = RECTIFICATION_NEAR_BOTTOM_PX,
|
||||
): boolean {
|
||||
return distanceFromBottom(scrollHeight, scrollTop, clientHeight) <= thresholdPx;
|
||||
}
|
||||
|
||||
export function shouldShowJumpToLatest(
|
||||
scrollHeight: number,
|
||||
scrollTop: number,
|
||||
clientHeight: number,
|
||||
choiceCardOpen = false,
|
||||
): boolean {
|
||||
const distance = distanceFromBottom(scrollHeight, scrollTop, clientHeight);
|
||||
if (distance <= RECTIFICATION_NEAR_BOTTOM_PX) return false;
|
||||
if (choiceCardOpen && distance <= RECTIFICATION_CHOICE_NEAR_BOTTOM_PX) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function shouldFollowLatest(followTail: boolean): boolean {
|
||||
return followTail === true;
|
||||
}
|
||||
Reference in New Issue
Block a user