Skip to content

Commit cb0cfce

Browse files
authored
chore(assistant): use ai components (#4112)
* chore: 1 * chore: 2 * chore: 3 * chore: 4 * chore: 5 * chore: 6 * chore: 7 * chore: 8 * chore: 9
1 parent c23bb4c commit cb0cfce

File tree

11 files changed

+118
-153
lines changed

11 files changed

+118
-153
lines changed

packages/paste-website/src/component-examples/AIChatLogExamples.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const MessageWithLoadingAndStop = () => {
101101
return (
102102
<AIChatLog>
103103
<AIChatMessage variant="bot">
104-
<AIChatMessageAuthor aria-label="AI said" bot>
104+
<AIChatMessageAuthor aria-label="AI said">
105105
Good Bot
106106
</AIChatMessageAuthor>
107107
<AIChatMessageBody>
@@ -120,7 +120,7 @@ const MessageWithLoading = () => {
120120
return (
121121
<AIChatLog>
122122
<AIChatMessage variant="bot">
123-
<AIChatMessageAuthor aria-label="AI said" bot>
123+
<AIChatMessageAuthor aria-label="AI said">
124124
Good Bot
125125
</AIChatMessageAuthor>
126126
<AIChatMessageBody>

packages/paste-website/src/components/assistant/AssistantCanvas.tsx

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useIsMutating, useQuery } from "@tanstack/react-query";
2+
import { AIChatLog } from "@twilio-paste/ai-chat-log";
23
import { Box } from "@twilio-paste/box";
3-
import { ChatBookend, ChatBookendItem, ChatLog } from "@twilio-paste/chat-log";
4+
import { Text } from "@twilio-paste/text";
45
import * as React from "react";
56
import { useShallow } from "zustand/react/shallow";
67

@@ -17,7 +18,6 @@ type AssistantCanvasProps = {
1718

1819
export const AssistantCanvas: React.FC<AssistantCanvasProps> = ({ selectedThreadID }) => {
1920
const [mounted, setMounted] = React.useState(false);
20-
const [logWidth, setLogWidth] = React.useState(0);
2121
const messages = useAssistantMessagesStore(useShallow((state) => state.messages));
2222
const setMessages = useAssistantMessagesStore(useShallow((state) => state.setMessages));
2323
const activeRun = useAssistantRunStore(useShallow((state) => state.activeRun));
@@ -48,8 +48,6 @@ export const AssistantCanvas: React.FC<AssistantCanvasProps> = ({ selectedThread
4848

4949
React.useEffect(() => {
5050
setMounted(true);
51-
// whats the width of the log? You'll need it to render the skeleton loader
52-
setLogWidth(loggerRef.current?.offsetWidth ?? 0);
5351
}, []);
5452

5553
// scroll to bottom of chat log when new messages are added
@@ -62,29 +60,48 @@ export const AssistantCanvas: React.FC<AssistantCanvasProps> = ({ selectedThread
6260
<Box ref={scrollerRef} tabIndex={0} overflowY="auto">
6361
<Box maxWidth="1000px" marginX="auto">
6462
{activeRun != null && <AssistantMessagePoller />}
65-
<ChatLog ref={loggerRef}>
66-
<ChatBookend>
67-
<ChatBookendItem>
63+
<AIChatLog ref={loggerRef}>
64+
<Box display="flex" flexDirection="column" rowGap="space40">
65+
<Text
66+
as="span"
67+
color="colorTextWeak"
68+
fontSize="fontSize20"
69+
lineHeight="lineHeight20"
70+
fontWeight="fontWeightMedium"
71+
textAlign="center"
72+
>
6873
Welcome to the Paste Design System Assistant! We&apos;re excited to have you here.
69-
</ChatBookendItem>
70-
</ChatBookend>
71-
<ChatBookend>
72-
<ChatBookendItem>
73-
Keep in mind that this is an experimental tool and so the information provided{" "}
74-
<strong>may not be entirely accurate</strong>.
75-
</ChatBookendItem>
76-
<ChatBookendItem>
74+
</Text>
75+
<Text
76+
as="span"
77+
color="colorTextWeak"
78+
fontSize="fontSize20"
79+
lineHeight="lineHeight20"
80+
fontWeight="fontWeightMedium"
81+
textAlign="center"
82+
>
83+
Keep in mind that this is an experimental tool and so the information provided may not be entirely
84+
accurate.
85+
</Text>
86+
<Text
87+
as="span"
88+
color="colorTextWeak"
89+
fontSize="fontSize20"
90+
lineHeight="lineHeight20"
91+
fontWeight="fontWeightMedium"
92+
textAlign="center"
93+
>
7794
Your conversations are not used to train OpenAI&apos;s models, but are stored by OpenAI.
78-
</ChatBookendItem>
79-
</ChatBookend>
95+
</Text>
96+
</Box>
8097
{messages?.map((threadMessage): React.ReactNode => {
8198
if (threadMessage.role === "assistant") {
8299
return <AssistantMessage key={threadMessage.id} threadMessage={threadMessage} />;
83100
}
84101
return <UserMessage key={threadMessage.id} threadMessage={threadMessage} />;
85102
})}
86-
{(isCreatingAResponse || activeRun != null) && <LoadingMessage maxWidth={logWidth} />}
87-
</ChatLog>
103+
{(isCreatingAResponse || activeRun != null) && <LoadingMessage />}
104+
</AIChatLog>
88105
</Box>
89106
</Box>
90107
);
Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
import { ChatComposer } from "@twilio-paste/chat-composer";
2-
import { $getRoot, ClearEditorPlugin, type EditorState } from "@twilio-paste/lexical-library";
1+
import { Button } from "@twilio-paste/button";
2+
import { ChatComposer, ChatComposerActionGroup, ChatComposerContainer } from "@twilio-paste/chat-composer";
3+
import { SendIcon } from "@twilio-paste/icons/esm/SendIcon";
4+
import {
5+
$getRoot,
6+
CLEAR_EDITOR_COMMAND,
7+
ClearEditorPlugin,
8+
type EditorState,
9+
type LexicalEditor,
10+
} from "@twilio-paste/lexical-library";
311
import * as React from "react";
412

513
import { useAssistantThreadsStore } from "../../stores/assistantThreadsStore";
614
import useStoreWithLocalStorage from "../../stores/useStore";
715
import { EnterKeySubmitPlugin } from "./EnterKeySubmitPlugin";
8-
import { FocusComposerPlugin } from "./FocusComposerPlugin";
9-
import { SendButtonPlugin } from "./SendButtonPlugin";
1016

1117
export const AssistantComposer: React.FC<{ onMessageCreation: (message: string, selectedThread: string) => void }> = ({
1218
onMessageCreation,
@@ -15,7 +21,7 @@ export const AssistantComposer: React.FC<{ onMessageCreation: (message: string,
1521
const threadsStore = useStoreWithLocalStorage(useAssistantThreadsStore, (state) => state);
1622
const selectedThread = threadsStore?.selectedThreadID;
1723

18-
const editorRef = React.useRef(null);
24+
const editorInstanceRef = React.useRef<LexicalEditor>(null);
1925

2026
const handleComposerChange = (editorState: EditorState): void => {
2127
editorState.read(() => {
@@ -29,24 +35,40 @@ export const AssistantComposer: React.FC<{ onMessageCreation: (message: string,
2935
onMessageCreation(message, selectedThread);
3036
};
3137

38+
React.useEffect(() => {
39+
editorInstanceRef.current?.focus();
40+
}, [editorInstanceRef, selectedThread]);
41+
3242
return (
33-
<ChatComposer
34-
maxHeight="size10"
35-
config={{
36-
namespace: "foo",
37-
onError: (error: Error) => {
38-
throw error;
39-
},
40-
}}
41-
ariaLabel="Message"
42-
placeholder="Type here..."
43-
onChange={handleComposerChange}
44-
ref={editorRef}
45-
>
46-
<ClearEditorPlugin />
47-
<SendButtonPlugin onClick={submitMessage} disabled={selectedThread == null} />
48-
<EnterKeySubmitPlugin onKeyDown={submitMessage} />
49-
<FocusComposerPlugin selectedThread={selectedThread} />
50-
</ChatComposer>
43+
<ChatComposerContainer variant="contained">
44+
<ChatComposer
45+
maxHeight="size10"
46+
config={{
47+
namespace: "foo",
48+
onError: (error: Error) => {
49+
throw error;
50+
},
51+
}}
52+
ariaLabel="Message"
53+
placeholder="Type here..."
54+
onChange={handleComposerChange}
55+
editorInstanceRef={editorInstanceRef}
56+
>
57+
<ClearEditorPlugin />
58+
<EnterKeySubmitPlugin onKeyDown={submitMessage} />
59+
</ChatComposer>
60+
<ChatComposerActionGroup>
61+
<Button
62+
variant="primary_icon"
63+
size="reset"
64+
onClick={() => {
65+
submitMessage();
66+
editorInstanceRef.current?.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
67+
}}
68+
>
69+
<SendIcon decorative={false} title="Send" />
70+
</Button>
71+
</ChatComposerActionGroup>
72+
</ChatComposerContainer>
5173
);
5274
};

packages/paste-website/src/components/assistant/AssistantEmptyState.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ export const AssistantEmptyState: React.FC<{ onCannedThreadCreation: (message: s
2020
}) => {
2121
return (
2222
<Box display="flex" justifyContent="center" alignItems="center" height="100vh">
23-
<Box maxWidth="900px" display="flex" flexDirection="column" rowGap="space190" paddingX="space120">
24-
<Box display="flex" columnGap="space190" alignItems="center">
23+
<Box maxWidth="900px" display="flex" flexDirection="column" rowGap="space150" paddingX="space120">
24+
<Box display="flex" columnGap="space150" alignItems="center">
2525
<Box>
2626
<Heading as="h1" variant="heading20">
2727
Welcome to the Paste Design System Assistant
@@ -39,7 +39,7 @@ export const AssistantEmptyState: React.FC<{ onCannedThreadCreation: (message: s
3939
<Link href="https://github.com/twilio-labs/paste/discussions/new/choose">Github Discussions</Link>.
4040
</Paragraph>
4141
</Box>
42-
<Image src={EmptyDoSomething} width={400} aria-hidden="true" alt="" priority />
42+
<Image src={EmptyDoSomething} width={300} aria-hidden="true" alt="" priority />
4343
</Box>
4444
<Box>
4545
<Heading as="h2" variant="heading30">

packages/paste-website/src/components/assistant/AssistantLayout.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,7 @@ const ThreadsHeader: React.FC<React.PropsWithChildren> = ({ children }) => {
5757
export const Composer: React.FC<React.PropsWithChildren> = ({ children }) => {
5858
return (
5959
<Box
60-
borderStyle="solid"
61-
borderWidth="borderWidth0"
62-
borderTopWidth="borderWidth10"
63-
borderColor="colorBorderWeak"
6460
backgroundColor="colorBackgroundBody"
65-
display="flex"
66-
flexDirection="row"
67-
columnGap="space30"
6861
paddingX="space70"
6962
paddingY="space50"
7063
position="sticky"
Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
1-
import { ChatBubble, ChatMessage, ChatMessageMeta, ChatMessageMetaItem } from "@twilio-paste/chat-log";
1+
import { AIChatMessage, AIChatMessageAuthor, AIChatMessageBody } from "@twilio-paste/ai-chat-log";
22
import { type ThreadMessage } from "openai/resources/beta/threads/messages";
33
import * as React from "react";
44

5-
import { Logo } from "../../assets/Logo";
65
import { formatTimestamp } from "../../utils/formatTimestamp";
76
import { AssistantMarkdown } from "./AssistantMarkdown";
87

98
export const AssistantMessage: React.FC<{ threadMessage: ThreadMessage }> = ({ threadMessage }) => {
109
return (
11-
<ChatMessage variant="inbound">
12-
<ChatBubble>
10+
<AIChatMessage variant="bot">
11+
<AIChatMessageAuthor aria-label={`said by paste assistant at ${formatTimestamp(threadMessage.created_at)}`}>
12+
PasteBot
13+
</AIChatMessageAuthor>
14+
<AIChatMessageBody>
1315
{threadMessage.content[0].type === "text" && (
1416
<AssistantMarkdown key={threadMessage.id}>{threadMessage.content[0].text.value}</AssistantMarkdown>
1517
)}
16-
</ChatBubble>
17-
<ChatMessageMeta aria-label={`said by the assistant at ${formatTimestamp(threadMessage.created_at)}`}>
18-
<ChatMessageMetaItem>
19-
<Logo size={20} />
20-
PasteBot ・ {formatTimestamp(threadMessage.created_at)}
21-
</ChatMessageMetaItem>
22-
</ChatMessageMeta>
23-
</ChatMessage>
18+
</AIChatMessageBody>
19+
</AIChatMessage>
2420
);
2521
};

packages/paste-website/src/components/assistant/FocusComposerPlugin.tsx

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,20 @@
1-
/* eslint-disable camelcase */
2-
import { Box } from "@twilio-paste/box";
3-
import { ChatBubble, ChatMessage, ChatMessageMeta, ChatMessageMetaItem } from "@twilio-paste/chat-log";
4-
import { SkeletonLoader } from "@twilio-paste/skeleton-loader";
5-
import { useUID } from "@twilio-paste/uid-library";
1+
import { AIChatMessage, AIChatMessageAuthor, AIChatMessageBody, AIChatMessageLoading } from "@twilio-paste/ai-chat-log";
62
import * as React from "react";
73

8-
import { Logo } from "../../assets/Logo";
9-
import { useAssistantRunStore } from "../../stores/assistantRunStore";
104
import { formatTimestamp } from "../../utils/formatTimestamp";
115

12-
const getRandomNumber = (max: number): number => {
13-
return Math.floor(Math.random() * max);
14-
};
15-
16-
const STATUS_MAP = {
17-
queued: "Queued...",
18-
in_progress: "Researching...",
19-
requires_action: "Researching...",
20-
cancelling: "Concelling...",
21-
cancelled: "Cancelled.",
22-
failed: "Failed.",
23-
completed: "Finished.",
24-
expired: "Expired.",
25-
};
26-
27-
export const LoadingMessage: React.FC<{ maxWidth: number }> = ({ maxWidth }) => {
28-
const activeRun = useAssistantRunStore((state) => state.activeRun);
29-
6+
export const LoadingMessage: React.FC = () => {
307
const newDateTime = new Date();
318
const timestamp = Math.floor(newDateTime.getTime() / 1000);
329

33-
const randomWidths = React.useMemo(() => {
34-
return Array.from({ length: 3 }, () => getRandomNumber(maxWidth));
35-
}, [maxWidth]);
36-
3710
return (
38-
<ChatMessage variant="inbound">
39-
<ChatBubble>
40-
<Box display="grid" rowGap="space30">
41-
{randomWidths.map((width) => (
42-
<SkeletonLoader key={useUID()} height="20px" width={`${width}px`} />
43-
))}
44-
</Box>
45-
</ChatBubble>
46-
<ChatMessageMeta aria-label={`said by the assistant at ${formatTimestamp(timestamp)}`}>
47-
<ChatMessageMetaItem>
48-
<Logo size={20} />
49-
PasteBot ・ {activeRun?.status ? STATUS_MAP[activeRun?.status] : "Thinking..."}
50-
</ChatMessageMetaItem>
51-
</ChatMessageMeta>
52-
</ChatMessage>
11+
<AIChatMessage variant="bot">
12+
<AIChatMessageAuthor aria-label={`said by paste assistant at ${formatTimestamp(timestamp)}`}>
13+
PasteBot
14+
</AIChatMessageAuthor>
15+
<AIChatMessageBody>
16+
<AIChatMessageLoading />
17+
</AIChatMessageBody>
18+
</AIChatMessage>
5319
);
5420
};
55-
/* eslint-enable camelcase */

packages/paste-website/src/components/assistant/SendButtonPlugin.tsx

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)