https://github.com/conversationalcomponents/chat-window
Basic chat window functionality
https://github.com/conversationalcomponents/chat-window
chat chat-window chatbot mobx mobx-react react reactjs typescript
Last synced: about 2 months ago
JSON representation
Basic chat window functionality
- Host: GitHub
- URL: https://github.com/conversationalcomponents/chat-window
- Owner: ConversationalComponents
- Created: 2020-01-10T12:22:36.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2023-01-26T21:53:11.000Z (about 3 years ago)
- Last Synced: 2025-09-15T11:57:12.845Z (7 months ago)
- Topics: chat, chat-window, chatbot, mobx, mobx-react, react, reactjs, typescript
- Language: TypeScript
- Size: 214 KB
- Stars: 8
- Watchers: 2
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# chat-window
Basic chat window functionality
install with ```npm install @conversationalcomponents/chat-window```
example:
```js
import React from "react";
import {ChatWindow} from "@conversationalcomponents/chat-window";
export const Example = () => (
);
```
An example with fake conversation:
```js
import React, {useState, useEffect} from "react";
import {ChatWindow} from "@conversationalcomponents/chat-window";
const makeMessage = (isUser: boolean, text: string, id: number) => ({
isUser,
message: text,
avatar: isUser ? "https://img.icons8.com/color/search/0" : "https://img.icons8.com/color/search/96",
id: `message_${id}`,
isLoading: false
});
const botReplies = ["Wow!", "Fascinating, please do go on", "Amazing!", "Really?", "If you say so..."];
export const Example = () => {
const [content, setContent] = useState([makeMessage(false, "Hello and welcome to the example!", 0)]);
useEffect(() => {
const lastEntry = content.length && content[content.length - 1];
lastEntry &&
lastEntry.isUser &&
setContent([...content, makeMessage(false, botReplies[Math.floor(Math.random() * botReplies.length)], 0)]);
}, [content]);
return (
setContent([...content, makeMessage(true, text, content.length)])}
/>
);
};
```
An example with custom header, typing animations (Typescript):
```js
import React, {useState, useEffect} from "react";
import {useUserTyping, useBotTyping, ChatWindow} from "@conversationalcomponents/chat-window";
import {ChatEntry} from "@conversationalcomponents/chat-window/types";
const botReplies = ["Wow!", "Fascinating, please do go on", "Amazing!", "Really?", "If you say so..."];
const getBotReply = () => botReplies[Math.floor(Math.random() * botReplies.length)];
const userAvatar = "https://img.icons8.com/color/search/0";
const botAvatar = "https://img.icons8.com/color/search/1";
export const Example = () => {
const [content, setContent] = useState([]);
const [lastInputValue, setLastInputValue] = useState("");
const [lastUnsubmittedInput, setLastUnsubmittedInput] = useState("");
useEffect(() => {
const lastEntry = content.length && content[content.length - 1];
if (!lastEntry || lastEntry.isUser) return;
setLastInputValue("");
}, [content]);
useEffect(() => {
lastInputValue && setLastUnsubmittedInput("");
}, [lastInputValue]);
useUserTyping(content, setContent, lastUnsubmittedInput, lastInputValue, userAvatar);
const isBotDoneTyping = useBotTyping(content, setContent, lastInputValue, botAvatar);
useEffect(() => {
if (!isBotDoneTyping) return;
const lastEntry = content.length && content[content.length - 1];
if (!lastEntry || lastEntry.isUser) return;
lastEntry.message = getBotReply();
lastEntry.isLoading = false;
}, [isBotDoneTyping]);
return (
HEADER}
content={content}
onChange={(text: string) => setLastUnsubmittedInput(text)}
onSubmit={(text: string) => setLastInputValue(text)}
/>
);
};
```
An example with typing animations that echoes user's input back:
```js
import React, {useState, useEffect} from "react";
import {ChatEntry} from "@conversationalcomponents/chat-window/types";
import {useUserTyping, useBotTyping, ChatWindow} from "@conversationalcomponents/chat-window";
const userAvatar = "https://img.icons8.com/color/search/0";
const botAvatar = "https://img.icons8.com/color/search/1";
export const Example = () => {
const [content, setContent] = useState([]);
const [lastInputValue, setLastInputValue] = useState("");
const [lastUnsubmittedInput, setLastUnsubmittedInput] = useState("");
const [nextBotReply, setNextBotReply] = useState("");
useEffect(() => {
const lastEntry = content.length && content[content.length - 1];
if (!lastEntry || lastEntry.isUser) return;
setNextBotReply(lastInputValue);
setLastInputValue("");
}, [content]);
useEffect(() => {
lastInputValue && setLastUnsubmittedInput("");
}, [lastInputValue]);
useUserTyping(content, setContent, lastUnsubmittedInput, lastInputValue, userAvatar);
const isBotDoneTyping = useBotTyping(content, setContent, lastInputValue, botAvatar);
useEffect(() => {
if (!isBotDoneTyping || !nextBotReply) return;
const lastEntry = content.length && content[content.length - 1];
if (!lastEntry || lastEntry.isUser) return;
lastEntry.message = nextBotReply;
lastEntry.isLoading = false;
setNextBotReply("");
}, [isBotDoneTyping]);
return (
HEADER}
content={content}
onChange={(text: string) => setLastUnsubmittedInput(text)}
onSubmit={(text: string) => setLastInputValue(text)}
/>
);
};
```