added fade in and color transition
This commit is contained in:
parent
a56a39f4c4
commit
b65195f0bd
3 changed files with 81 additions and 62 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import { GitBranch } from "lucide-react";
|
import { GitBranch } from "lucide-react";
|
||||||
|
import { motion } from "motion/react";
|
||||||
import DogIcon from "@/components/logo/dog-icon";
|
import DogIcon from "@/components/logo/dog-icon";
|
||||||
import { MarkdownRenderer } from "@/components/markdown-renderer";
|
import { MarkdownRenderer } from "@/components/markdown-renderer";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
@ -30,44 +31,52 @@ export function AssistantMessage({
|
||||||
isCompleted = false,
|
isCompleted = false,
|
||||||
}: AssistantMessageProps) {
|
}: AssistantMessageProps) {
|
||||||
return (
|
return (
|
||||||
<Message
|
<motion.div
|
||||||
icon={
|
initial={{ opacity: 0, y: -20 }}
|
||||||
<div className="w-8 h-8 rounded-lg bg-accent/20 flex items-center justify-center flex-shrink-0 select-none">
|
animate={{ opacity: 1, y: 0 }}
|
||||||
<DogIcon
|
transition={{ duration: 0.4, delay: 0.2, ease: "easeOut" }}
|
||||||
className="h-6 w-6"
|
className={isCompleted ? "opacity-50" : ""}
|
||||||
disabled={isCompleted}
|
>
|
||||||
|
<Message
|
||||||
|
icon={
|
||||||
|
<div className="w-8 h-8 rounded-lg bg-accent/20 flex items-center justify-center flex-shrink-0 select-none">
|
||||||
|
<DogIcon
|
||||||
|
className="h-6 w-6 transition-colors duration-300"
|
||||||
|
disabled={isCompleted}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
actions={
|
||||||
|
showForkButton && onFork ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onFork}
|
||||||
|
className="opacity-0 group-hover:opacity-100 transition-opacity p-1 hover:bg-accent rounded text-muted-foreground hover:text-foreground"
|
||||||
|
title="Fork conversation from here"
|
||||||
|
>
|
||||||
|
<GitBranch className="h-3 w-3" />
|
||||||
|
</button>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FunctionCalls
|
||||||
|
functionCalls={functionCalls}
|
||||||
|
messageIndex={messageIndex}
|
||||||
|
expandedFunctionCalls={expandedFunctionCalls}
|
||||||
|
onToggle={onToggle}
|
||||||
|
/>
|
||||||
|
<div className="relative">
|
||||||
|
<MarkdownRenderer
|
||||||
|
className={cn("text-sm py-1.5 transition-colors duration-300", isCompleted ? "text-placeholder-foreground" : "text-foreground")}
|
||||||
|
chatMessage={
|
||||||
|
isStreaming
|
||||||
|
? content +
|
||||||
|
' <span class="inline-block w-1 h-4 bg-primary ml-1 animate-pulse"></span>'
|
||||||
|
: content
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
</Message>
|
||||||
actions={
|
</motion.div>
|
||||||
showForkButton && onFork ? (
|
|
||||||
<button
|
|
||||||
onClick={onFork}
|
|
||||||
className="opacity-0 group-hover:opacity-100 transition-opacity p-1 hover:bg-accent rounded text-muted-foreground hover:text-foreground"
|
|
||||||
title="Fork conversation from here"
|
|
||||||
>
|
|
||||||
<GitBranch className="h-3 w-3" />
|
|
||||||
</button>
|
|
||||||
) : undefined
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FunctionCalls
|
|
||||||
functionCalls={functionCalls}
|
|
||||||
messageIndex={messageIndex}
|
|
||||||
expandedFunctionCalls={expandedFunctionCalls}
|
|
||||||
onToggle={onToggle}
|
|
||||||
/>
|
|
||||||
<div className="relative">
|
|
||||||
<MarkdownRenderer
|
|
||||||
className={cn("text-sm py-1.5", isCompleted ? "text-placeholder-foreground" : "text-foreground")}
|
|
||||||
chatMessage={
|
|
||||||
isStreaming
|
|
||||||
? content +
|
|
||||||
' <span class="inline-block w-1 h-4 bg-primary ml-1 animate-pulse"></span>'
|
|
||||||
: content
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Message>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { User } from "lucide-react";
|
import { User } from "lucide-react";
|
||||||
|
import { motion } from "motion/react";
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||||
import { useAuth } from "@/contexts/auth-context";
|
import { useAuth } from "@/contexts/auth-context";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
@ -13,29 +14,36 @@ export function UserMessage({ content, isCompleted }: UserMessageProps) {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Message
|
<motion.div
|
||||||
icon={
|
initial={{ opacity: 0, y: -20 }}
|
||||||
<Avatar className="w-8 h-8 rounded-lg flex-shrink-0 select-none">
|
animate={{ opacity: 1, y: 0 }}
|
||||||
<AvatarImage draggable={false} src={user?.picture} alt={user?.name} />
|
transition={{ duration: 0.4, delay: 0.2, ease: "easeOut" }}
|
||||||
<AvatarFallback
|
className={isCompleted ? "opacity-50" : ""}
|
||||||
className={cn(
|
|
||||||
isCompleted ? "text-placeholder-foreground" : "text-primary",
|
|
||||||
"text-sm bg-accent/20 rounded-lg",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{user?.name ? user.name.charAt(0).toUpperCase() : <User className="h-4 w-4" />}
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<p
|
<Message
|
||||||
className={cn(
|
icon={
|
||||||
"text-foreground text-sm py-1.5 whitespace-pre-wrap break-words overflow-wrap-anywhere",
|
<Avatar className="w-8 h-8 rounded-lg flex-shrink-0 select-none">
|
||||||
isCompleted ? "text-placeholder-foreground" : "text-foreground",
|
<AvatarImage draggable={false} src={user?.picture} alt={user?.name} />
|
||||||
)}
|
<AvatarFallback
|
||||||
|
className={cn(
|
||||||
|
isCompleted ? "text-placeholder-foreground" : "text-primary",
|
||||||
|
"text-sm bg-accent/20 rounded-lg transition-colors duration-300",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{user?.name ? user.name.charAt(0).toUpperCase() : <User className="h-4 w-4" />}
|
||||||
|
</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{content}
|
<p
|
||||||
</p>
|
className={cn(
|
||||||
</Message>
|
"text-foreground text-sm py-1.5 whitespace-pre-wrap break-words overflow-wrap-anywhere transition-colors duration-300",
|
||||||
|
isCompleted ? "text-placeholder-foreground" : "text-foreground",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</p>
|
||||||
|
</Message>
|
||||||
|
</motion.div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,12 @@ export function OnboardingContent({
|
||||||
const handleNudgeClick = async (nudge: string) => {
|
const handleNudgeClick = async (nudge: string) => {
|
||||||
setSelectedNudge(nudge);
|
setSelectedNudge(nudge);
|
||||||
setAssistantMessage(null);
|
setAssistantMessage(null);
|
||||||
|
setTimeout(async () => {
|
||||||
await sendMessage({
|
await sendMessage({
|
||||||
prompt: nudge,
|
prompt: nudge,
|
||||||
previousResponseId: responseId || undefined,
|
previousResponseId: responseId || undefined,
|
||||||
});
|
});
|
||||||
|
}, 1500);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determine which message to show (streaming takes precedence)
|
// Determine which message to show (streaming takes precedence)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue