fix: resolve scroll flickering on message send and improve thinking state animation (#1333)

This commit is contained in:
josh 2025-11-29 13:02:24 +00:00 committed by GitHub
parent d0b6f37aee
commit a3802348fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 225 additions and 174 deletions

View file

@ -1,7 +1,6 @@
"use client";
import type { UseChatHelpers } from "@ai-sdk/react";
import equal from "fast-deep-equal";
import { motion } from "framer-motion";
import { memo, useState } from "react";
import type { Vote } from "@/lib/db/schema";
import type { ChatMessage } from "@/lib/types";
@ -33,7 +32,7 @@ const PurePreviewMessage = ({
setMessages,
regenerate,
isReadonly,
requiresScrollPadding,
requiresScrollPadding: _requiresScrollPadding,
}: {
chatId: string;
message: ChatMessage;
@ -53,12 +52,10 @@ const PurePreviewMessage = ({
useDataStream();
return (
<motion.div
animate={{ opacity: 1 }}
className="group/message w-full"
<div
className="group/message fade-in w-full animate-in duration-200"
data-role={message.role}
data-testid={`message-${message.role}`}
initial={{ opacity: 0 }}
>
<div
className={cn("flex w-full items-start gap-2 md:gap-3", {
@ -77,7 +74,6 @@ const PurePreviewMessage = ({
"gap-2 md:gap-4": message.parts?.some(
(p) => p.type === "text" && p.text?.trim()
),
"min-h-96": message.role === "assistant" && requiresScrollPadding,
"w-full":
(message.role === "assistant" &&
message.parts?.some(
@ -282,7 +278,7 @@ const PurePreviewMessage = ({
)}
</div>
</div>
</motion.div>
</div>
);
};
@ -310,30 +306,30 @@ export const PreviewMessage = memo(
);
export const ThinkingMessage = () => {
const role = "assistant";
return (
<motion.div
animate={{ opacity: 1 }}
className="group/message w-full"
data-role={role}
<div
className="group/message fade-in w-full animate-in duration-300"
data-role="assistant"
data-testid="message-assistant-loading"
exit={{ opacity: 0, transition: { duration: 0.5 } }}
initial={{ opacity: 0 }}
transition={{ duration: 0.2 }}
>
<div className="flex items-start justify-start gap-3">
<div className="-mt-1 flex size-8 shrink-0 items-center justify-center rounded-full bg-background ring-1 ring-border">
<SparklesIcon size={14} />
<div className="animate-pulse">
<SparklesIcon size={14} />
</div>
</div>
<div className="flex w-full flex-col gap-2 md:gap-4">
<div className="p-0 text-muted-foreground text-sm">
Thinking...
<div className="flex items-center gap-1 p-0 text-muted-foreground text-sm">
<span className="animate-pulse">Thinking</span>
<span className="inline-flex">
<span className="animate-bounce [animation-delay:0ms]">.</span>
<span className="animate-bounce [animation-delay:150ms]">.</span>
<span className="animate-bounce [animation-delay:300ms]">.</span>
</span>
</div>
</div>
</div>
</motion.div>
</div>
);
};