Session switch: land at the bottom instantly with the question dock open
- Chat now remounts per session (key={chat.id}): fresh StickToBottom,
fresh DockOverlay (no cross-session morph from the previous shell
height), fresh useChat.
- Conversation initial="instant" (was "smooth"): the mount scroll to
bottom is a jump, not a slide.
- DockOverlay skips the pending-question scroll/expand effect for the
session's INITIAL pending question (dock starts expanded; the initial
scroll positions us) — previously it fired a second smooth
scrollToBottom right after the library's initial scroll (the visible
'pause, then the quiz pops and pushes everything up').
- The dock-variant fade/rise no longer plays for the session's opening
variant; reserved for mid-session transitions.
Verified live: client-side switch settles at d=1px from the bottom within
one frame of content swap, dock open from the first frame, both
directions (quiz session, plain session).
This commit is contained in:
@@ -17,6 +17,7 @@ export default async function ChatPage({
|
|||||||
if (!chat) notFound();
|
if (!chat) notFound();
|
||||||
return (
|
return (
|
||||||
<Chat
|
<Chat
|
||||||
|
key={chat.id}
|
||||||
chatId={chat.id}
|
chatId={chat.id}
|
||||||
title={chat.title}
|
title={chat.title}
|
||||||
initialMessages={chat.messages as TeacherUIMessage[]}
|
initialMessages={chat.messages as TeacherUIMessage[]}
|
||||||
|
|||||||
+13
-8
@@ -95,7 +95,7 @@ export function Chat({
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="relative min-h-0 flex-1">
|
<div className="relative min-h-0 flex-1">
|
||||||
<Conversation className="h-full">
|
<Conversation className="h-full" initial="instant">
|
||||||
<ConversationContent className="min-h-full gap-0 p-0">
|
<ConversationContent className="min-h-full gap-0 p-0">
|
||||||
<div className={`${COLUMN} flex flex-1 flex-col gap-4 pt-4`}>
|
<div className={`${COLUMN} flex flex-1 flex-col gap-4 pt-4`}>
|
||||||
{messages.length === 0 && !busy && (
|
{messages.length === 0 && !busy && (
|
||||||
@@ -208,14 +208,16 @@ function DockOverlay({
|
|||||||
const [expanded, setExpanded] = useState(true);
|
const [expanded, setExpanded] = useState(true);
|
||||||
|
|
||||||
const pendingId = pending?.toolCallId ?? null;
|
const pendingId = pending?.toolCallId ?? null;
|
||||||
|
const initialPendingRef = useRef(pendingId);
|
||||||
|
|
||||||
// New question: open expanded if the learner is following at the bottom
|
// New question MID-SESSION: open expanded if the learner is following at
|
||||||
// (scroll to reveal it); if they're reading history, arrive as the slim bar.
|
// the bottom (scroll to reveal it); reading history → arrive as the bar.
|
||||||
|
// On session mount the dock simply starts expanded at the bottom (the
|
||||||
|
// library's instant initial scroll positions us) — no scroll, no morph.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (pendingId) {
|
if (!pendingId || pendingId === initialPendingRef.current) return;
|
||||||
setExpanded(isAtBottom);
|
setExpanded(isAtBottom);
|
||||||
if (isAtBottom) void scrollToBottom();
|
if (isAtBottom) void scrollToBottom();
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- fire only when a NEW question lands
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- fire only when a NEW question lands
|
||||||
}, [pendingId]);
|
}, [pendingId]);
|
||||||
|
|
||||||
@@ -258,6 +260,9 @@ function DockOverlay({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mode = pending ? `question:${pending.toolCallId}` : "chat";
|
const mode = pending ? `question:${pending.toolCallId}` : "chat";
|
||||||
|
// The opening variant of a session appears instantly — the fade/rise is
|
||||||
|
// reserved for mid-session transitions.
|
||||||
|
const initialModeRef = useRef(mode);
|
||||||
|
|
||||||
// Height morph: animate the shell from its previous height to its new one
|
// Height morph: animate the shell from its previous height to its new one
|
||||||
// whenever the variant (chat ↔ question ↔ collapsed bar) changes. Typing
|
// whenever the variant (chat ↔ question ↔ collapsed bar) changes. Typing
|
||||||
@@ -298,7 +303,7 @@ function DockOverlay({
|
|||||||
<div className="bg-background pb-4">
|
<div className="bg-background pb-4">
|
||||||
<div className={COLUMN}>
|
<div className={COLUMN}>
|
||||||
<div ref={shellRef} className="pointer-events-auto overflow-hidden rounded-2xl border bg-card shadow-lg">
|
<div ref={shellRef} className="pointer-events-auto overflow-hidden rounded-2xl border bg-card shadow-lg">
|
||||||
<div key={mode} className="dock-variant">
|
<div key={mode} className={mode === initialModeRef.current ? undefined : "dock-variant"}>
|
||||||
{pending ? (
|
{pending ? (
|
||||||
<QuestionDock
|
<QuestionDock
|
||||||
toolName={pending.tool as "quiz" | "ask_user_question"}
|
toolName={pending.tool as "quiz" | "ask_user_question"}
|
||||||
|
|||||||
Reference in New Issue
Block a user