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
26 lines
743 B
TypeScript
26 lines
743 B
TypeScript
"use client";
|
|
|
|
import { ArrowDown } from "lucide-react";
|
|
|
|
/**
|
|
* The "back to the newest turn" control both chat surfaces show once the
|
|
* reader has scrolled away from the bottom. It hangs off the composer's top
|
|
* edge (the composer wrap is its containing block) so it never reflows the
|
|
* transcript or the composer, and it is a real button in document order.
|
|
*/
|
|
export function JumpToLatestButton({ onClick }: Readonly<{ onClick: () => void }>) {
|
|
return (
|
|
<div className="jump-to-latest">
|
|
<button
|
|
type="button"
|
|
className="jump-to-latest__button"
|
|
aria-label="跳到最新"
|
|
onClick={onClick}
|
|
>
|
|
<ArrowDown aria-hidden="true" />
|
|
跳到最新
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|