ChatbotProvider

API reference for managing chatbot state and configuration with ChatbotProvider.


Introduction

ChatbotProvider provides the state, configuration, and actions used by custom chatbot interfaces.

It is useful when you want to build your own chatbot UI while keeping react-ai-chat responsible for chat state, theme configuration, and communication with your API route.

Import

import { ChatbotProvider, useChatbotContext } from "react-ai-chat";

Basic usage

Wrap your chatbot UI with ChatbotProvider:

<ChatbotProvider>
  <YourChatbot />
</ChatbotProvider>

Components inside the provider can then access the chatbot state and actions through useChatbotContext().

function YourChatbot() {
  const { messages, input, setInput, handleSubmit, isLoading } =
    useChatbotContext();

  return <div>{/* Your chatbot UI */}</div>;
}

Provider props

ChatbotProvider accepts configuration for the API endpoint, initial state, position, theme, and error handling.

children

children: React.ReactNode;

The chatbot UI rendered inside the provider.

<ChatbotProvider>
  <CustomChatbot />
</ChatbotProvider>

This is required.

apiEndpoint

apiEndpoint?: string

The endpoint used for chat requests.

Default: "/api/chat"

<ChatbotProvider apiEndpoint="/api/assistant">
  <CustomChatbot />
</ChatbotProvider>

Your server route must expose a compatible POST handler at this endpoint.

See API Route.

initialOpen

initialOpen?: boolean

Controls whether the chatbot starts in the open state.

Default: false

<ChatbotProvider initialOpen>
  <CustomChatbot />
</ChatbotProvider>

position

position?: "bottom-right" | "bottom-left" | "top-right" | "top-left"

Sets the chatbot position.

Default: "bottom-right"

<ChatbotProvider position="bottom-left">
  <CustomChatbot />
</ChatbotProvider>

The position is available through useChatbotContext().

themeMode

themeMode?: "auto" | "light" | "dark"

Controls the chatbot's color mode.

Default: "auto"

<ChatbotProvider themeMode="dark">
  <CustomChatbot />
</ChatbotProvider>

With "auto", the chatbot follows the user's system color preference.

theme

theme?: ChatbotTheme

Provides custom theme token overrides.

<ChatbotProvider
  theme={{
    primaryColor: "#7c3aed",
    primaryForeground: "#ffffff",
  }}
>
  <CustomChatbot />
</ChatbotProvider>

See Theming for the available theme tokens.

onError

onError?: (error: Error) => void

Called when the chatbot encounters an error.

<ChatbotProvider
  onError={(error) => {
    console.error("Chatbot error:", error);
  }}
>
  <CustomChatbot />
</ChatbotProvider>

You can use this callback to connect chatbot errors to your application's error reporting.

See Errors for the available error types and codes.

Context

Use useChatbotContext() inside a ChatbotProvider to access the chatbot state and actions.

const {
  isOpen,
  setIsOpen,
  input,
  setInput,
  messages,
  status,
  isLoading,
  handleSubmit,
  position,
  themeMode,
  themeStyles,
} = useChatbotContext();

The context provides the following values.

isOpen

Indicates whether the chatbot is currently open.

isOpen: boolean;
const { isOpen } = useChatbotContext();

return <p>{isOpen ? "Chat is open" : "Chat is closed"}</p>;

setIsOpen

Updates the chatbot's open state.

setIsOpen: (open: boolean) => void;

Open the chatbot:

<button onClick={() => setIsOpen(true)}>Open chat</button>

Close it:

<button onClick={() => setIsOpen(false)}>Close chat</button>

input

The current value of the message input.

input: string;
<input value={input} />

setInput

Updates the message input.

setInput: (input: string) => void;

Example:

<input value={input} onChange={(event) => setInput(event.target.value)} />

messages

The current conversation messages.

messages: ReturnType < typeof useChat > ["messages"];

The messages use the AI SDK message structure.

{
  messages.map((message) => (
    <div key={message.id}>
      {message.parts.map((part, index) =>
        part.type === "text" ? <p key={index}>{part.text}</p> : null,
      )}
    </div>
  ));
}

status

The current status of the chat request.

status: ReturnType < typeof useChat > ["status"];

You can use the status to determine the current state of the chat request.

const { status } = useChatbotContext();

return <p>Status: {status}</p>;

The exact status values are provided by the AI SDK version used by react-ai-chat.

isLoading

Indicates whether the chatbot is currently generating a response.

isLoading: boolean;

Use it to disable controls or display a loading state:

{
  isLoading && <span>Thinking...</span>;
}

For example:

<button disabled={isLoading}>{isLoading ? "Thinking..." : "Send"}</button>

handleSubmit

Submits the current input and starts a chat request.

handleSubmit: (e?: SubmitEvent<HTMLFormElement>, customText?: string) =>
  Promise<void>;

It can be used directly from a button:

<button onClick={() => handleSubmit()}>Send</button>

When used with a form, pass the submit event:

<form
  onSubmit={(event) => {
    event.preventDefault();
    handleSubmit(event);
  }}
>
  <button type="submit">Send</button>
</form>

You can also submit custom text:

<button onClick={() => handleSubmit(undefined, "Tell me about this project")}>
  Ask about the project
</button>

position

The current chatbot position.

position:
  | "bottom-right"
  | "bottom-left"
  | "top-right"
  | "top-left";

The value comes from the provider configuration.

const { position } = useChatbotContext();

return <div data-position={position}>...</div>;

themeMode

The active chatbot theme mode.

themeMode: "auto" | "light" | "dark";
const { themeMode } = useChatbotContext();

return <p>Theme: {themeMode}</p>;

themeStyles

The computed theme styles for the chatbot.

themeStyles: React.CSSProperties;

These styles contain the CSS custom properties generated from the configured theme.

They can be applied to a custom chatbot container:

const { themeStyles } = useChatbotContext();

return <section style={themeStyles}>{/* Custom chatbot UI */}</section>;

This allows a custom interface to use the same theme configuration provided to ChatbotProvider.

Building a custom input

The context API makes it possible to replace the generated input with your own component.

function CustomInput() {
  const { input, setInput, handleSubmit, isLoading } = useChatbotContext();

  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        handleSubmit(event);
      }}
    >
      <input
        value={input}
        onChange={(event) => setInput(event.target.value)}
        placeholder="Ask a question..."
      />

      <button type="submit" disabled={isLoading || !input.trim()}>
        {isLoading ? "Thinking..." : "Send"}
      </button>
    </form>
  );
}

Building a custom message list

You can control how messages are rendered.

function CustomMessages() {
  const { messages } = useChatbotContext();

  return (
    <div>
      {messages.map((message) => (
        <div key={message.id}>
          <strong>{message.role}</strong>

          <div>
            {message.parts.map((part, index) =>
              part.type === "text" ? <p key={index}>{part.text}</p> : null,
            )}
          </div>
        </div>
      ))}
    </div>
  );
}

This lets you control the presentation while the provider continues to manage the conversation.

Building a custom trigger

You can use the open state to create your own trigger:

function CustomTrigger() {
  const { isOpen, setIsOpen } = useChatbotContext();

  return (
    <button onClick={() => setIsOpen(!isOpen)}>
      {isOpen ? "Close chat" : "Open chat"}
    </button>
  );
}

Using theme styles

You can apply the computed theme styles to your custom UI:

function CustomChatbot() {
  const { themeStyles, themeMode } = useChatbotContext();

  return (
    <section style={themeStyles} data-theme={themeMode}>
      <h2>AI Assistant</h2>
    </section>
  );
}

This is useful when building a custom interface that should use the same theme configuration as the provider.

Full custom UI

The provider and context can be combined to create an entire chatbot interface:

import { ChatbotProvider, useChatbotContext } from "react-ai-chat";

function CustomChatbot() {
  const {
    messages,
    input,
    setInput,
    handleSubmit,
    isLoading,
    isOpen,
    setIsOpen,
    themeStyles,
  } = useChatbotContext();

  if (!isOpen) {
    return <button onClick={() => setIsOpen(true)}>Open chat</button>;
  }

  return (
    <section style={themeStyles}>
      <header>
        <h2>AI Assistant</h2>

        <button onClick={() => setIsOpen(false)}>Close</button>
      </header>

      <div>
        {messages.map((message) => (
          <div key={message.id}>
            <strong>{message.role}</strong>

            {message.parts.map((part, index) =>
              part.type === "text" ? <p key={index}>{part.text}</p> : null,
            )}
          </div>
        ))}
      </div>

      <form
        onSubmit={(event) => {
          event.preventDefault();
          handleSubmit(event);
        }}
      >
        <input
          value={input}
          onChange={(event) => setInput(event.target.value)}
          placeholder="Ask something..."
        />

        <button type="submit" disabled={isLoading || !input.trim()}>
          {isLoading ? "Thinking..." : "Send"}
        </button>
      </form>
    </section>
  );
}

export default function App() {
  return (
    <ChatbotProvider
      apiEndpoint="/api/chat"
      position="bottom-right"
      themeMode="auto"
    >
      <CustomChatbot />
    </ChatbotProvider>
  );
}

Provider requirement

useChatbotContext() must be called from a component rendered inside ChatbotProvider.

This will cause an error:

function MyComponent() {
  const context = useChatbotContext();

  return <div />;
}

when MyComponent is rendered without a provider.

Wrap it with:

<ChatbotProvider>
  <MyComponent />
</ChatbotProvider>

Provider vs ready-made Chatbot

Use <Chatbot /> when you want the complete built-in interface.

Use ChatbotProvider when you want to build the interface yourself while using react-ai-chat for chat state, request handling, configuration, and theme information.

The generated chatbot uses this approach internally.

Complete provider example

import {
  ChatbotProvider,
  useChatbotContext,
} from "react-ai-chat";

function CustomChatbot() {
  const {
    messages,
    input,
    setInput,
    handleSubmit,
    isLoading,
    isOpen,
    setIsOpen,
    position,
    themeMode,
    themeStyles,
  } = useChatbotContext();

  return (
    <section
      style={themeStyles}
      data-position={position}
      data-theme={themeMode}
    >
      {!isOpen ? (
        <button onClick={() => setIsOpen(true)}>
          Open chat
        </button>
      ) : (
        <>
          <header>
            <h2>AI Assistant</h2>
            <button onClick={() => setIsOpen(false)}>
              Close
            </button>
          </header>

          <div>
            {messages.map((message) => (
              <div key={message.id}>
                {message.parts.map((part, index) =>
                  part.type === "text" ? (
                    <p key={index}>{part.text}</p>
                  ) : null,
                )}
              </div>
            )}
          </div>

          <form
            onSubmit={(event) => {
              event.preventDefault();
              handleSubmit(event);
            }}
          >
            <input
              value={input}
              onChange={(event) => setInput(event.target.value)}
            />

            <button
              type="submit"
              disabled={isLoading || !input.trim()}
            >
              {isLoading ? "Thinking..." : "Send"}
            </button>
          </form>
        </>
      )}
    </section>
  );
}

export default function App() {
  return (
    <ChatbotProvider
      apiEndpoint="/api/chat"
      initialOpen={false}
      position="bottom-right"
      themeMode="auto"
      theme={{
        primaryColor: "#7c3aed",
        primaryForeground: "#ffffff",
      }}
      onError={(error) => {
        console.error("Chatbot error:", error);
      }}
    >
      <CustomChatbot />
    </ChatbotProvider>
  );
}

When to use this API

Use ChatbotProvider when you need custom control over the chatbot UI while keeping the package's state and request handling.

For a complete ready-made interface, use <Chatbot />.

For an editable starting point, use the generated chatbot:

npx react-ai-chat init

The generated components are built around ChatbotProvider and useChatbotContext().

On this page