First, use the useTypewriter hook to get access to some useful functions and variables for controlling the typewriter feed.
import * as PrettyChat from 'pretty-chat';
export const Demo = () => {
const {
// helper functions
feedText,
endTextFeed,
resetTypewriter,
// variables
cachedText,
incrementor,
markdownSegments,
} = PrettyChat.useTypewriter();
};
Use the 3 helper functions to feed chunks of streaming text to your typewriter.
const handleSendMessage = () => {
// handle an interrupt by closing the current stream before sending new message
if (eventSourceRef.current) {
eventSourceRef.current.close();
eventSourceRef.current = null;
}
resetTypewriter(); // Prepare the typewriter for next message
... implement stream event handlers below ...
}
eventSourceRef.current.onmessage = (event) => {
const chunk = event.data;
feedText(chunk); // Feed data to your typewriter as it arrives
dispatch(addBotMessageToChatList(chunk));
};
...
eventSourceRef.current.addEventListener('end', () => {
endTextFeed(); // Inform the typewriter it should expect to stop processing text soon
dispatch(markEndOfBotResponse());
if (eventSourceRef.current) {
eventSourceRef.current.close();
eventSourceRef.current = null;
}
});
Finally, implement the Typewriter component in your JSX.
Customize it by passing in edgeColor, restColor, and duration.
< div className = { styles.chatBox } >
{
chatList.map((message, index) => {
// user entries
if (message.type === "user") {
return (
<div key={index} className={styles.right}>
{message.text}
</div>
);
}
// bot entries
return (
<div key={index} className={styles.left}>
<PrettyChat.Typewriter
// Pass in raw text from your stream, or the complete text if not currently streaming
rawText={Array.isArray(chatList[index].text) ? chatList[index].text.join("") : cachedText}
// Set isTyping to true for the one message in the ChatList that is actively typing
isTyping={isLast(index) && !isFirst(index)}
// Pass the incrementor through so the component can keep rendering characters from your stream
incrementor={incrementor}
// Pass in markdownSegments so the Typewriter can render them appropriately
markdownSegments={markdownSegments}
// Define an edge color which will fade to rest color
edgeColor="#ff03ee"
// Define a rest color for the text to settle into
restColor="black"
// Define a duration for your edge fade
edgeDuration={.5}
/>
</div>
);
})
}
</div >