Interaction

Interaction

Overview

You can manage threads using the API reference, or pass your own callback functions that will be called after the user interacts with a thread.

For the latest list of callback functions, see the API – Threads page.

This example demonstrates how callback functions operate during thread interactions:

Collapse code
Expand code
<ChatPage
  initialThread={threads[0]}
  threads={threads}
  handleStopMessageStreaming={handleStopMessageStreaming}
  onUserMessageSent={onUserMessageSent}
  onFirstMessageSent={onFirstMessageSent}
  onThreadDeleted={onThreadDeleted}
  onChangeCurrentThread={onChangeCurrentThread}
  handleCreateNewThread={handleCreateNewThread}
/>
import * as React from "react";
import {
  ChatPage,
  useAssistantAnswerMock,
  Thread,
} from "@plteam/chat-ui";
import Box from "@mui/material/Box";
import Snackbar, { SnackbarCloseReason } from "@mui/material/Snackbar";
import IconButton from "@mui/material/IconButton";
import CloseIcon from "@mui/icons-material/Close";

let counter = 0;

const App: React.FC = () => {
  const [open, setOpen] = React.useState(false);
  const [text, setText] = React.useState('');

  const openSnackbar = (text: string) => {
    setText(text);
    setOpen(true);
  };

  const handleClose = (_event: React.SyntheticEvent | Event, reason?: SnackbarCloseReason) => {
    if (reason === 'clickaway') {
      return;
    }
    setOpen(false);
  };

  const [threads] = React.useState<Thread[]>([
    {
      id: "test-thread",
      title: "Second thread",
      date: (new Date('2025-01-18T12:00:00.000Z')).toISOString(),
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: "Hello!",
          },
        },
        {
          role: "assistant",
          content: "Hello there! How can I assist you today?",
        },
      ],
    },
    {
      id: "test-thread2",
      title: "First thread",
      date: (new Date('2024-12-12T12:00:00.000Z')).toISOString(),
      messages: [
        {
          role: "user",
          content: "Hello, how are you today?",
        },
        {
          role: "assistant",
          content: "Hi there! I'm doing great, thanks for asking. What can I help you with this morning?",
        },
      ],
    },
  ]);

  const onFirstMessageSent = ({ thread }: { thread: Thread }) => {
    openSnackbar(`The first message in thread "${thread.title}" has been sent`);
  }

  const onThreadDeleted = ({ thread }: { thread: Thread }) => {
    openSnackbar(`Thread deleted: ${thread.title}`);
  }

  const onChangeCurrentThread = ({ thread }: { thread: Thread }) => {
    openSnackbar(`Current thread changed: ${thread.title}`);
  }

  const handleCreateNewThread = (): Thread => {
    openSnackbar('Opened a new thread with our data');
    counter++;
    return ({
      id: `thread${counter}`,
      title: `Thread #${counter}`,
      messages: [],
      date: new Date().toISOString(),
    });
  }

  const snackBarActions = React.useMemo(() => (
    <IconButton
      size="small"
      aria-label="close"
      color="inherit"
      onClick={handleClose}
    >
      <CloseIcon fontSize="small" />
    </IconButton>
  ), [handleClose]);


  const { onUserMessageSent, handleStopMessageStreaming } =
    useAssistantAnswerMock();

  return (
    <>
      <Box height={"100dvh"} width={"100dvw"}>
        <ChatPage
          initialThread={threads[0]}
          threads={threads}
          handleStopMessageStreaming={handleStopMessageStreaming}
          onUserMessageSent={onUserMessageSent}
          onFirstMessageSent={onFirstMessageSent}
          onThreadDeleted={onThreadDeleted}
          onChangeCurrentThread={onChangeCurrentThread}
          handleCreateNewThread={handleCreateNewThread}
        />
      </Box>
      <Snackbar
        open={open}
        onClose={handleClose}
        message={text}
        action={snackBarActions}
      />
    </>
  );
}

export default App;