diff --git a/packages/paste-website/src/component-examples/AIChatLogExamples.ts b/packages/paste-website/src/component-examples/AIChatLogExamples.ts index a1622bae7b..ff9e831a7e 100644 --- a/packages/paste-website/src/component-examples/AIChatLogExamples.ts +++ b/packages/paste-website/src/component-examples/AIChatLogExamples.ts @@ -101,7 +101,7 @@ const MessageWithLoadingAndStop = () => { return ( - + Good Bot @@ -120,7 +120,7 @@ const MessageWithLoading = () => { return ( - + Good Bot diff --git a/packages/paste-website/src/components/assistant/AssistantCanvas.tsx b/packages/paste-website/src/components/assistant/AssistantCanvas.tsx index ccd4124d08..725c9fae0e 100644 --- a/packages/paste-website/src/components/assistant/AssistantCanvas.tsx +++ b/packages/paste-website/src/components/assistant/AssistantCanvas.tsx @@ -1,6 +1,7 @@ import { useIsMutating, useQuery } from "@tanstack/react-query"; +import { AIChatLog } from "@twilio-paste/ai-chat-log"; import { Box } from "@twilio-paste/box"; -import { ChatBookend, ChatBookendItem, ChatLog } from "@twilio-paste/chat-log"; +import { Text } from "@twilio-paste/text"; import * as React from "react"; import { useShallow } from "zustand/react/shallow"; @@ -17,7 +18,6 @@ type AssistantCanvasProps = { export const AssistantCanvas: React.FC = ({ selectedThreadID }) => { const [mounted, setMounted] = React.useState(false); - const [logWidth, setLogWidth] = React.useState(0); const messages = useAssistantMessagesStore(useShallow((state) => state.messages)); const setMessages = useAssistantMessagesStore(useShallow((state) => state.setMessages)); const activeRun = useAssistantRunStore(useShallow((state) => state.activeRun)); @@ -48,8 +48,6 @@ export const AssistantCanvas: React.FC = ({ selectedThread React.useEffect(() => { setMounted(true); - // whats the width of the log? You'll need it to render the skeleton loader - setLogWidth(loggerRef.current?.offsetWidth ?? 0); }, []); // scroll to bottom of chat log when new messages are added @@ -62,29 +60,48 @@ export const AssistantCanvas: React.FC = ({ selectedThread {activeRun != null && } - - - + + + Welcome to the Paste Design System Assistant! We're excited to have you here. - - - - - Keep in mind that this is an experimental tool and so the information provided{" "} - may not be entirely accurate. - - + + + Keep in mind that this is an experimental tool and so the information provided may not be entirely + accurate. + + Your conversations are not used to train OpenAI's models, but are stored by OpenAI. - - + + {messages?.map((threadMessage): React.ReactNode => { if (threadMessage.role === "assistant") { return ; } return ; })} - {(isCreatingAResponse || activeRun != null) && } - + {(isCreatingAResponse || activeRun != null) && } + ); diff --git a/packages/paste-website/src/components/assistant/AssistantComposer.tsx b/packages/paste-website/src/components/assistant/AssistantComposer.tsx index a44aef1d55..767fb2046d 100644 --- a/packages/paste-website/src/components/assistant/AssistantComposer.tsx +++ b/packages/paste-website/src/components/assistant/AssistantComposer.tsx @@ -1,12 +1,18 @@ -import { ChatComposer } from "@twilio-paste/chat-composer"; -import { $getRoot, ClearEditorPlugin, type EditorState } from "@twilio-paste/lexical-library"; +import { Button } from "@twilio-paste/button"; +import { ChatComposer, ChatComposerActionGroup, ChatComposerContainer } from "@twilio-paste/chat-composer"; +import { SendIcon } from "@twilio-paste/icons/esm/SendIcon"; +import { + $getRoot, + CLEAR_EDITOR_COMMAND, + ClearEditorPlugin, + type EditorState, + type LexicalEditor, +} from "@twilio-paste/lexical-library"; import * as React from "react"; import { useAssistantThreadsStore } from "../../stores/assistantThreadsStore"; import useStoreWithLocalStorage from "../../stores/useStore"; import { EnterKeySubmitPlugin } from "./EnterKeySubmitPlugin"; -import { FocusComposerPlugin } from "./FocusComposerPlugin"; -import { SendButtonPlugin } from "./SendButtonPlugin"; export const AssistantComposer: React.FC<{ onMessageCreation: (message: string, selectedThread: string) => void }> = ({ onMessageCreation, @@ -15,7 +21,7 @@ export const AssistantComposer: React.FC<{ onMessageCreation: (message: string, const threadsStore = useStoreWithLocalStorage(useAssistantThreadsStore, (state) => state); const selectedThread = threadsStore?.selectedThreadID; - const editorRef = React.useRef(null); + const editorInstanceRef = React.useRef(null); const handleComposerChange = (editorState: EditorState): void => { editorState.read(() => { @@ -29,24 +35,40 @@ export const AssistantComposer: React.FC<{ onMessageCreation: (message: string, onMessageCreation(message, selectedThread); }; + React.useEffect(() => { + editorInstanceRef.current?.focus(); + }, [editorInstanceRef, selectedThread]); + return ( - { - throw error; - }, - }} - ariaLabel="Message" - placeholder="Type here..." - onChange={handleComposerChange} - ref={editorRef} - > - - - - - + + { + throw error; + }, + }} + ariaLabel="Message" + placeholder="Type here..." + onChange={handleComposerChange} + editorInstanceRef={editorInstanceRef} + > + + + + + + + ); }; diff --git a/packages/paste-website/src/components/assistant/AssistantEmptyState.tsx b/packages/paste-website/src/components/assistant/AssistantEmptyState.tsx index b0e570b3b7..b915d90398 100644 --- a/packages/paste-website/src/components/assistant/AssistantEmptyState.tsx +++ b/packages/paste-website/src/components/assistant/AssistantEmptyState.tsx @@ -20,8 +20,8 @@ export const AssistantEmptyState: React.FC<{ onCannedThreadCreation: (message: s }) => { return ( - - + + Welcome to the Paste Design System Assistant @@ -39,7 +39,7 @@ export const AssistantEmptyState: React.FC<{ onCannedThreadCreation: (message: s Github Discussions. - + diff --git a/packages/paste-website/src/components/assistant/AssistantLayout.tsx b/packages/paste-website/src/components/assistant/AssistantLayout.tsx index 7351a704b7..d7086681b8 100644 --- a/packages/paste-website/src/components/assistant/AssistantLayout.tsx +++ b/packages/paste-website/src/components/assistant/AssistantLayout.tsx @@ -57,14 +57,7 @@ const ThreadsHeader: React.FC = ({ children }) => { export const Composer: React.FC = ({ children }) => { return ( = ({ threadMessage }) => { return ( - - + + + PasteBot + + {threadMessage.content[0].type === "text" && ( {threadMessage.content[0].text.value} )} - - - - - PasteBot ・ {formatTimestamp(threadMessage.created_at)} - - - + + ); }; diff --git a/packages/paste-website/src/components/assistant/FocusComposerPlugin.tsx b/packages/paste-website/src/components/assistant/FocusComposerPlugin.tsx deleted file mode 100644 index f45cdda77d..0000000000 --- a/packages/paste-website/src/components/assistant/FocusComposerPlugin.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { useLexicalComposerContext } from "@twilio-paste/lexical-library"; -import * as React from "react"; - -export const FocusComposerPlugin = ({ selectedThread }: { selectedThread?: string }): null => { - const [editor] = useLexicalComposerContext(); - - React.useEffect(() => { - editor.focus(); - }, [editor, selectedThread]); - return null; -}; diff --git a/packages/paste-website/src/components/assistant/LoadingMessage.tsx b/packages/paste-website/src/components/assistant/LoadingMessage.tsx index 2c92a38a75..d6d63a394f 100644 --- a/packages/paste-website/src/components/assistant/LoadingMessage.tsx +++ b/packages/paste-website/src/components/assistant/LoadingMessage.tsx @@ -1,55 +1,20 @@ -/* eslint-disable camelcase */ -import { Box } from "@twilio-paste/box"; -import { ChatBubble, ChatMessage, ChatMessageMeta, ChatMessageMetaItem } from "@twilio-paste/chat-log"; -import { SkeletonLoader } from "@twilio-paste/skeleton-loader"; -import { useUID } from "@twilio-paste/uid-library"; +import { AIChatMessage, AIChatMessageAuthor, AIChatMessageBody, AIChatMessageLoading } from "@twilio-paste/ai-chat-log"; import * as React from "react"; -import { Logo } from "../../assets/Logo"; -import { useAssistantRunStore } from "../../stores/assistantRunStore"; import { formatTimestamp } from "../../utils/formatTimestamp"; -const getRandomNumber = (max: number): number => { - return Math.floor(Math.random() * max); -}; - -const STATUS_MAP = { - queued: "Queued...", - in_progress: "Researching...", - requires_action: "Researching...", - cancelling: "Concelling...", - cancelled: "Cancelled.", - failed: "Failed.", - completed: "Finished.", - expired: "Expired.", -}; - -export const LoadingMessage: React.FC<{ maxWidth: number }> = ({ maxWidth }) => { - const activeRun = useAssistantRunStore((state) => state.activeRun); - +export const LoadingMessage: React.FC = () => { const newDateTime = new Date(); const timestamp = Math.floor(newDateTime.getTime() / 1000); - const randomWidths = React.useMemo(() => { - return Array.from({ length: 3 }, () => getRandomNumber(maxWidth)); - }, [maxWidth]); - return ( - - - - {randomWidths.map((width) => ( - - ))} - - - - - - PasteBot ・ {activeRun?.status ? STATUS_MAP[activeRun?.status] : "Thinking..."} - - - + + + PasteBot + + + + + ); }; -/* eslint-enable camelcase */ diff --git a/packages/paste-website/src/components/assistant/SendButtonPlugin.tsx b/packages/paste-website/src/components/assistant/SendButtonPlugin.tsx deleted file mode 100644 index 6b0271b64c..0000000000 --- a/packages/paste-website/src/components/assistant/SendButtonPlugin.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Box } from "@twilio-paste/box"; -import { Button } from "@twilio-paste/button"; -import { SendIcon } from "@twilio-paste/icons/esm/SendIcon"; -import { CLEAR_EDITOR_COMMAND, useLexicalComposerContext } from "@twilio-paste/lexical-library"; - -export const SendButtonPlugin = ({ onClick, disabled }: { onClick: () => void; disabled: boolean }): JSX.Element => { - const [editor] = useLexicalComposerContext(); - - const handleSend = (): void => { - onClick(); - editor.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined); - }; - - return ( - - - - ); -}; diff --git a/packages/paste-website/src/components/assistant/UserMessage.tsx b/packages/paste-website/src/components/assistant/UserMessage.tsx index b8feb9eaff..21477ca2d4 100644 --- a/packages/paste-website/src/components/assistant/UserMessage.tsx +++ b/packages/paste-website/src/components/assistant/UserMessage.tsx @@ -1,4 +1,5 @@ -import { ChatBubble, ChatMessage, ChatMessageMeta, ChatMessageMetaItem } from "@twilio-paste/chat-log"; +import { AIChatMessage, AIChatMessageAuthor, AIChatMessageBody } from "@twilio-paste/ai-chat-log"; +import { UserIcon } from "@twilio-paste/icons/esm/UserIcon"; import { type ThreadMessage } from "openai/resources/beta/threads/messages"; import * as React from "react"; @@ -7,15 +8,18 @@ import { AssistantMarkdown } from "./AssistantMarkdown"; export const UserMessage: React.FC<{ threadMessage: ThreadMessage }> = ({ threadMessage }) => { return ( - - + + + You + + {threadMessage.content[0].type === "text" && ( {threadMessage.content[0].text.value} )} - - - You ・ {formatTimestamp(threadMessage.created_at)} - - + + ); }; diff --git a/packages/paste-website/src/pages/components/ai-chat-log/api.mdx b/packages/paste-website/src/pages/components/ai-chat-log/api.mdx index 5045614559..0fc36b82e6 100644 --- a/packages/paste-website/src/pages/components/ai-chat-log/api.mdx +++ b/packages/paste-website/src/pages/components/ai-chat-log/api.mdx @@ -52,9 +52,9 @@ import { AIChatMessage, AIChatMessageAuthor, AIChatMessageBody, - AIChatMessageFeedback, AIChatMessageLoading, - AIChatMessageMeta, + AIChatMessageActionGroup, + AIChatMessageActionCard, } from "@twilio-paste/ai-chat-log"; export const Basic = () => {