From 8188ed39994985f35bb3e41cf583e3d0f20efe87 Mon Sep 17 00:00:00 2001 From: parththakkar106 Date: Mon, 20 Jul 2026 16:57:16 +0530 Subject: [PATCH] Play screen UX: sticky header + fix streaming autoscroll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pin the play header (Plot/Memory/Scripts/Insights toggles) just below the top nav so they stay reachable without scrolling back up to the first message. - Fix streaming autoscroll: snap to the real document bottom instantly instead of smooth-scrolling to storyEndRef. That ref sits above the sticky composer, so block:'end' stopped short — hiding the latest line behind the input bar and yanking the reader back up when they scrolled down. Smooth behavior also never settled at per-token speed. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01TEpWMjnfPqzZ13nPMoGhs5 --- frontend/src/index.css | 12 ++++++++++++ frontend/src/pages/Play.jsx | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index a0b67bd..baf8fff 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -288,6 +288,18 @@ button:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: n .play-page { display: flex; flex-direction: column; min-height: calc(100vh - 56px); } +/* Keep the Plot/Memory/Scripts/Insights toggles reachable while the story + scrolls — pin the header just below the 56px top nav. */ +.play-page .page-header { + position: sticky; + top: 56px; + z-index: 5; + background: var(--bg); + margin-bottom: 12px; + padding: 12px 0; + border-bottom: 1px solid var(--border); +} + .story { flex: 1; font-family: var(--font-story); diff --git a/frontend/src/pages/Play.jsx b/frontend/src/pages/Play.jsx index 61f4100..4af09b5 100644 --- a/frontend/src/pages/Play.jsx +++ b/frontend/src/pages/Play.jsx @@ -444,8 +444,12 @@ export default function Play() { }, []) useEffect(() => { + // Snap to the real document bottom (below the sticky composer), not to + // storyEndRef — that ref sits above the composer, so block:'end' would + // stop short and fight a reader scrolling down. Instant, not smooth: at + // streaming speed a queued smooth animation never settles. if (pinnedRef.current) { - storyEndRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' }) + window.scrollTo({ top: document.documentElement.scrollHeight }) } }, [actions, streaming, reasoningStream])