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?: stringThe 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?: booleanControls 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?: ChatbotThemeProvides custom theme token overrides.
<ChatbotProvider
theme={{
primaryColor: "#7c3aed",
primaryForeground: "#ffffff",
}}
>
<CustomChatbot />
</ChatbotProvider>See Theming for the available theme tokens.
onError
onError?: (error: Error) => voidCalled 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 initThe generated components are built around ChatbotProvider and useChatbotContext().