feat: add flip display effect

This commit is contained in:
Henry Li
2026-01-16 20:40:09 +08:00
parent c265734c6e
commit 91eff99f01
3 changed files with 41 additions and 7 deletions

View File

@@ -0,0 +1,29 @@
import { AnimatePresence, motion } from "motion/react";
import { cn } from "@/lib/utils";
export function FlipDisplay({
uniqueKey,
children,
className,
}: {
uniqueKey: string;
children: React.ReactNode;
className?: string;
}) {
return (
<div className={cn("relative h-6 overflow-hidden", className)}>
<AnimatePresence mode="wait">
<motion.div
key={uniqueKey}
initial={{ y: 8, opacity: 0 }}
animate={{ y: 2, opacity: 1 }}
exit={{ y: -8, opacity: 0 }}
transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }}
>
{children}
</motion.div>
</AnimatePresence>
</div>
);
}

View File

@@ -29,6 +29,8 @@ import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
import { extractTitleFromMarkdown } from "@/core/utils/markdown"; import { extractTitleFromMarkdown } from "@/core/utils/markdown";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { FlipDisplay } from "../flip-display";
export function MessageGroup({ export function MessageGroup({
className, className,
messages, messages,
@@ -62,17 +64,20 @@ export function MessageGroup({
{open && steps.length > 1 ? ( {open && steps.length > 1 ? (
<div>{steps.length} steps</div> <div>{steps.length} steps</div>
) : ( ) : (
<FlipDisplay uniqueKey={`step-${steps.length}`}>
<MessageResponse rehypePlugins={rehypePlugins}> <MessageResponse rehypePlugins={rehypePlugins}>
{label} {label}
</MessageResponse> </MessageResponse>
</FlipDisplay>
)} )}
</div> </div>
</div> </div>
<div> <div>
{!open && steps.length > 1 && ( {!open && steps.length > 1 && (
<div className="tet-xs opacity-60"> <div>
{steps.length - 1} more step {steps.length - 1 > 1
{steps.length - 1 > 1 ? "s" : ""} ? `${steps.length - 1} more steps`
: `${steps.length - 1} more step`}
</div> </div>
)} )}
</div> </div>

View File

@@ -28,7 +28,7 @@ export function MessageList({
<Conversation <Conversation
className={cn("flex size-full flex-col justify-center pt-2", className)} className={cn("flex size-full flex-col justify-center pt-2", className)}
> >
<ConversationContent className="mx-auto w-full max-w-(--container-width-md) gap-12"> <ConversationContent className="mx-auto w-full max-w-(--container-width-md) gap-10">
{groupMessages( {groupMessages(
thread.messages, thread.messages,
(groupedMessages) => { (groupedMessages) => {