Add thinking placeholder message (#496)

This commit is contained in:
Jeremy 2024-11-06 15:21:28 +03:00 committed by GitHub
parent 0001c24d09
commit b5c165714b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 13 deletions

View file

@ -3,17 +3,10 @@
import Link from 'next/link'; import Link from 'next/link';
import { type User } from 'next-auth'; import { type User } from 'next-auth';
import { PlusIcon, VercelIcon } from '@/components/custom/icons'; import { PlusIcon } from '@/components/custom/icons';
import { SidebarHistory } from '@/components/custom/sidebar-history'; import { SidebarHistory } from '@/components/custom/sidebar-history';
import { SidebarUserNav } from '@/components/custom/sidebar-user-nav'; import { SidebarUserNav } from '@/components/custom/sidebar-user-nav';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import {
Card,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { import {
Sidebar, Sidebar,
SidebarContent, SidebarContent,

View file

@ -8,7 +8,7 @@ import useSWR, { useSWRConfig } from 'swr';
import { useWindowSize } from 'usehooks-ts'; import { useWindowSize } from 'usehooks-ts';
import { ChatHeader } from '@/components/custom/chat-header'; import { ChatHeader } from '@/components/custom/chat-header';
import { PreviewMessage } from '@/components/custom/message'; import { PreviewMessage, ThinkingMessage } from '@/components/custom/message';
import { useScrollToBottom } from '@/components/custom/use-scroll-to-bottom'; import { useScrollToBottom } from '@/components/custom/use-scroll-to-bottom';
import { Vote } from '@/db/schema'; import { Vote } from '@/db/schema';
import { fetcher } from '@/lib/utils'; import { fetcher } from '@/lib/utils';
@ -100,6 +100,12 @@ export function Chat({
/> />
))} ))}
{isLoading &&
messages.length > 0 &&
messages[messages.length - 1].role === 'user' && (
<ThinkingMessage />
)}
<div <div
ref={messagesEndRef} ref={messagesEndRef}
className="shrink-0 min-w-[24px] min-h-[24px]" className="shrink-0 min-w-[24px] min-h-[24px]"

View file

@ -796,9 +796,9 @@ export const ThumbDownIcon = ({ size = 16 }: { size?: number }) => (
></path> ></path>
</svg> </svg>
); );
export const ChevronDownIcon = ({ size = 16 }: { size?: number }) => ( export const ChevronDownIcon = ({ size = 16 }: { size?: number }) => (
<svg <svg
height={size} height={size}
strokeLinejoin="round" strokeLinejoin="round"
viewBox="0 0 16 16" viewBox="0 0 16 16"
@ -813,3 +813,26 @@ export const ChevronDownIcon = ({ size = 16 }: { size?: number }) => (
></path> ></path>
</svg> </svg>
); );
export const SparklesIcon = ({ size = 16 }: { size?: number }) => (
<svg
height={size}
strokeLinejoin="round"
viewBox="0 0 16 16"
width={size}
style={{ color: 'currentcolor' }}
>
<path
d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z"
fill="currentColor"
></path>
<path
d="M14.5 4.5V5H13.5V4.5C13.5 3.94772 13.0523 3.5 12.5 3.5H12V3V2.5H12.5C13.0523 2.5 13.5 2.05228 13.5 1.5V1H14H14.5V1.5C14.5 2.05228 14.9477 2.5 15.5 2.5H16V3V3.5H15.5C14.9477 3.5 14.5 3.94772 14.5 4.5Z"
fill="currentColor"
></path>
<path
d="M8.40706 4.92939L8.5 4H9.5L9.59294 4.92939C9.82973 7.29734 11.7027 9.17027 14.0706 9.40706L15 9.5V10.5L14.0706 10.5929C11.7027 10.8297 9.82973 12.7027 9.59294 15.0706L9.5 16H8.5L8.40706 15.0706C8.17027 12.7027 6.29734 10.8297 3.92939 10.5929L3 10.5V9.5L3.92939 9.40706C6.29734 9.17027 8.17027 7.29734 8.40706 4.92939Z"
fill="currentColor"
></path>
</svg>
);

View file

@ -3,13 +3,13 @@
import { Message } from 'ai'; import { Message } from 'ai';
import cx from 'classnames'; import cx from 'classnames';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { Sparkles } from 'lucide-react';
import { Dispatch, SetStateAction } from 'react'; import { Dispatch, SetStateAction } from 'react';
import { Vote } from '@/db/schema'; import { Vote } from '@/db/schema';
import { UICanvas } from './canvas'; import { UICanvas } from './canvas';
import { DocumentToolCall, DocumentToolResult } from './document'; import { DocumentToolCall, DocumentToolResult } from './document';
import { SparklesIcon } from './icons';
import { Markdown } from './markdown'; import { Markdown } from './markdown';
import { MessageActions } from './message-actions'; import { MessageActions } from './message-actions';
import { PreviewAttachment } from './preview-attachment'; import { PreviewAttachment } from './preview-attachment';
@ -49,7 +49,7 @@ export const PreviewMessage = ({
> >
{message.role === 'assistant' && ( {message.role === 'assistant' && (
<div className="size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border"> <div className="size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border">
<Sparkles className="size-4" /> <SparklesIcon size={14} />
</div> </div>
)} )}
@ -148,3 +148,35 @@ export const PreviewMessage = ({
</motion.div> </motion.div>
); );
}; };
export const ThinkingMessage = () => {
const role = 'assistant';
return (
<motion.div
className="w-full mx-auto max-w-3xl px-4 group/message "
initial={{ y: 5, opacity: 0 }}
animate={{ y: 0, opacity: 1, transition: { delay: 1 } }}
data-role={role}
>
<div
className={cx(
'flex gap-4 group-data-[role=user]/message:px-3 w-full group-data-[role=user]/message:w-fit group-data-[role=user]/message:ml-auto group-data-[role=user]/message:max-w-2xl group-data-[role=user]/message:py-2 rounded-xl',
{
'group-data-[role=user]/message:bg-muted': true,
}
)}
>
<div className="size-8 flex items-center rounded-full justify-center ring-1 shrink-0 ring-border">
<SparklesIcon size={14} />
</div>
<div className="flex flex-col gap-2 w-full">
<div className="flex flex-col gap-4 text-muted-foreground">
Thinking...
</div>
</div>
</div>
</motion.div>
);
};