Chat · Booper

2 min read Original article ↗

For now, we only support React. To install our React library, run:

import React from 'react';

import {ChatProvider, Frame, Launcher, useChat} from '@booper/react';

const Chat = () => {

const scrollRef = React.useRef<HTMLDivElement | null>(null);

const [content, setMessageContent] = React.useState('');

const {messages, open, toggle, send, refresh} = useChat();

React.useEffect(() => {

scrollRef.current?.scrollIntoView();

}, [messages.length]);

const handleSendMessage = async (e: React.FormEvent<HTMLFormElement>) => {

e.preventDefault();

setMessageContent('');

await send({content});

await refresh();

};

return (

<>

<Frame open={open}>

<div className="flex h-[70vh] w-96 flex-col overflow-hidden rounded-lg border bg-white text-gray-900 shadow-lg">

<div className="bg-gradient-to-r from-gray-900 via-gray-800 to-gray-700 px-4 py-4 text-gray-100 dark:border-gray-700">

<h1 className="mt-1 text-xl font-bold text-white">Hi there 👋</h1>

<p className="text-sm text-gray-200">

Let us know if you have any questions!

</p>

</div>

<ul className="flex-1 overflow-scroll border-b p-4">

{messages.map((message, index) => {

const isMe = message.source === 'chat'; // other sources: 'discord' and 'bot'

const next = messages[index + 1];

const isNextSame = next && next.source === message.source;

return (

<li

key={index}

className={`flex ${

isMe ? 'justify-end pl-8' : 'justify-start pr-8'

} ${isNextSame ? 'mb-1' : 'mb-3'}`}

>

<div

className={`rounded-md border px-3 py-2 text-sm ${

isMe ? 'bg-gray-800 text-white' : 'bg-gray-200'

}`}

>

{message.content}

</div>

</li>

);

})}

<div ref={scrollRef} />

</ul>

<form onSubmit={handleSendMessage}>

<input

className="w-full border-none bg-white p-4 text-sm outline-none"

placeholder="Type your message..."

value={content}

onChange={(e) => setMessageContent(e.target.value)}

/>

</form>

</div>

</Frame>

<Launcher open={open}>

<button

className="inline-flex h-10 w-10 items-center justify-center rounded-full bg-gray-800 text-sm font-medium text-gray-50 transition-colors hover:bg-gray-800/90 disabled:pointer-events-none disabled:opacity-70"

onClick={toggle}

>

{open ? (

<XIcon className="h-5 w-5 animate-in fade-in-0 duration-200" />

) : (

<ChatIcon className="h-5 w-5 animate-in fade-in-0 duration-200" />

)}

</button>

</Launcher>

</>

);

};

export default function App() {

return (

<ChatProvider appId={YOUR_APP_ID}>

<Chat />

</ChatProvider>

);

};