react-ai-chatkit
v1.1.0
Published
A customizable React and TypeScript chat UI component for AI assistants, SaaS applications, and chatbot interfaces.
Downloads
978
Maintainers
Readme
🤖 React AI ChatKit
A customizable React + TypeScript chat component for AI assistants, SaaS applications, internal tools, and chatbot interfaces.
📸 Preview
✨ Features
- 🎨 Light & Dark themes with a consistent internal color system
- 🎨 Custom primary color
- 🤖 AI & User avatars (image or custom fallback)
- 🎛️ Fully customizable header, empty state, input, and send button
- 💬 Modern chat interface
- 📝 Markdown rendering (headings, lists, links, blockquotes, inline code, tables)
- 📄 Syntax highlighted code blocks with copy button
- 📋 Copy message button with accessible feedback
- 🔄 Regenerate last assistant response (optional)
- ⌨️ Enter to send, Shift + Enter for new lines
- ⌨️ Animated typing indicator and send-button loading state
- ⏰ Message timestamps with optional formatter
- 📱 Responsive design with no horizontal overflow
- ⚡ TypeScript support with exported types
What's new in v1.1.0
- Regenerate response — optional
onRegeneratecallback adds a regenerate button to the last assistant message - Message actions — copy and regenerate actions with accessible keyboard support
- Streaming-friendly — progressive assistant content updates render cleanly without visual glitches
- Empty & disabled states — improved visual handling for empty conversations and disabled input
All existing v1.0.x functionality is fully preserved. No breaking changes.
📦 Installation
npm install react-ai-chatkitor
yarn add react-ai-chatkitor
pnpm add react-ai-chatkit🚀 Quick Start
import { AIChatBox } from "react-ai-chatkit";
import type { Message } from "react-ai-chatkit";
const messages: Message[] = [
{
id: "1",
text: "Hello! How can I help you?",
sender: "ai",
},
];
export default function App() {
return (
<AIChatBox
messages={messages}
onSendMessage={(message) => console.log(message)}
/>
);
}🎨 Customization
import { AIChatBox } from "react-ai-chatkit";
import type { Message } from "react-ai-chatkit";
const messages: Message[] = [
{
id: "1",
text: "Hello! How can I help you?",
sender: "ai",
timestamp: "10:00",
},
];
export default function App() {
return (
<AIChatBox
messages={messages}
onSendMessage={(message) => console.log(message)}
title="AI Assistant"
subtitle="Online"
theme="light"
primaryColor="#6366f1"
width="500px"
height="600px"
aiAvatarFallback={<span>🤖</span>}
userAvatarFallback={<span>🙂</span>}
emptyStateTitle="How can I help?"
emptyStateDescription="Ask me anything."
placeholder="Type your message..."
maxLength={500}
autoFocus
sendButtonText="Send"
timestampFormatter={(timestamp) => `at ${timestamp}`}
/>
);
}Custom header, send button, and message styles
<AIChatBox
messages={messages}
onSendMessage={handleSend}
header={
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<strong>Support</strong>
</div>
}
headerActions={<button type="button">Settings</button>}
sendButtonContent={
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="m5 12 4 4L19 6" />
</svg>
}
userMessageStyle={{ marginTop: 4 }}
aiMessageClassName="ai-message-box"
/>Custom class names
<AIChatBox
messages={messages}
onSendMessage={handleSend}
containerClassName="my-chat-wrapper"
messageListClassName="my-chat-messages"
inputClassName="my-chat-input"
sendButtonClassName="my-chat-send"
/>Each prop is merged with the built-in class on the same element, so existing styling is preserved and you can layer your own CSS on top. containerClassName targets the root chat container, messageListClassName the scrollable messages area, inputClassName the textarea, and sendButtonClassName the send button.
Placeholder and send button label
<AIChatBox
messages={messages}
onSendMessage={handleSend}
placeholder="Ask me anything..."
sendButtonLabel="Submit message"
/>placeholder customizes the textarea placeholder and sendButtonLabel sets the send button's accessible label/title without changing its visual content.
Typing / sending state
<AIChatBox
messages={messages}
onSendMessage={handleSend}
isTyping={isWaiting}
isSending={isWaiting} // disables the send button and shows a spinner
/>Regenerate last response
<AIChatBox
messages={messages}
onSendMessage={handleSend}
onRegenerate={() => {
// Re-trigger your AI generation logic
// The component shows a regenerate button on the last AI message
}}
/>When onRegenerate is provided, a regenerate button appears on the last AI message. Hover or focus the message to reveal the action buttons. The button is keyboard accessible and has an appropriate accessible label.
Message actions
Each assistant message shows action buttons on hover (or always on touch devices):
- Copy — copies the message text to the clipboard with visual feedback
- Regenerate — shown only on the last AI message when
onRegenerateis provided
Both buttons are keyboard accessible with visible focus indicators and aria-label attributes.
⚙️ Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| messages | Message[] | Required | Chat messages |
| onSendMessage | (message: string) => void | undefined | Called when a message is sent |
| title | string | "React AI Chatbox" | Header title |
| subtitle | string | undefined | Optional header subtitle |
| header | ReactNode | undefined | Replaces the default header content |
| headerActions | ReactNode | undefined | Action content shown on the right side of the header |
| theme | "light" | "dark" | "dark" | Theme |
| primaryColor | string | #7c3aed | Primary accent color |
| width | string | number | "450px" | Component width |
| height | string | number | "520px" | Component height |
| placeholder | string | "Type your message..." | Input placeholder |
| disabled | boolean | false | Disable input |
| isTyping | boolean | false | Show typing indicator |
| isSending | boolean | false | Disable send and show a spinner while sending |
| showHeader | boolean | true | Show header |
| showAvatars | boolean | true | Show avatars |
| aiAvatar | string | undefined | AI avatar image URL |
| userAvatar | string | undefined | User avatar image URL |
| aiAvatarFallback | ReactNode | Robot icon | Content shown when no AI avatar image is set |
| userAvatarFallback | ReactNode | Person icon | Content shown when no user avatar image is set |
| aiMessageClassName | string | undefined | Class added to AI message rows |
| aiMessageStyle | React.CSSProperties | undefined | Style added to AI message rows |
| userMessageClassName | string | undefined | Class added to user message rows |
| userMessageStyle | React.CSSProperties | undefined | Style added to user message rows |
| showCopyButton | boolean | true | Show the message copy button |
| showSendButton | boolean | true | Show the send button |
| sendButtonText | string | "Ask AI" | Send button text (and accessible label for custom content) |
| sendButtonContent | ReactNode | undefined | Custom send button content/icon |
| sendButtonLabel | string | "Send" | Accessible label (title/aria-label) of the send button |
| showTimestamps | boolean | true | Show timestamps |
| timestampFormatter | (timestamp: string) => string | undefined | Format the rendered timestamp |
| emptyStateTitle | string | "Start a conversation" | Empty state title |
| emptyStateDescription | string | "Send a message to begin chatting." | Empty state description |
| emptyStateContent | ReactNode | undefined | Replaces the default empty state content |
| inputProps | TextareaHTMLAttributes<HTMLTextAreaElement> | undefined | Native textarea props |
| inputClassName | string | undefined | Class added to the textarea |
| inputStyle | React.CSSProperties | undefined | Style added to the textarea |
| inputContainerClassName | string | undefined | Class added to the input container (footer) |
| inputContainerStyle | React.CSSProperties | undefined | Style added to the input container (footer) |
| maxInputLength | number | undefined | Maximum input length (deprecated alias of maxLength) |
| maxLength | number | undefined | Maximum input length; prevents typing beyond the limit |
| autoFocus | boolean | false | Focus the textarea automatically on initial render |
| className | string | undefined | Class added to the component root |
| containerClassName | string | undefined | Additional class added to the component root |
| messageListClassName | string | undefined | Additional class added to the scrollable messages container |
| sendButtonClassName | string | undefined | Additional class added to the send button |
| style | React.CSSProperties | undefined | Style added to the component root |
| onRegenerate | () => void | undefined | Callback when the regenerate button is clicked on the last AI message |
Message type
interface Message {
id: string;
text: string;
sender: "user" | "ai";
timestamp?: string;
}Theme colors
The internal color system is exported for custom styles:
import { getChatColors } from "react-ai-chatkit";
const colors = getChatColors("dark");
// { background, text, border, aiBubble, inputBackground, mutedText, success }📄 Markdown Example
const aiMessage = {
sender: "ai",
text: `
# Welcome
Here is some code:
\`\`\`tsx
function Button() {
return <button>Hello</button>;
}
\`\`\`
`,
};Markdown with tables, lists, quotes, and links is supported out of the box.
📚 TypeScript Usage
import { AIChatBox } from "react-ai-chatkit";
import type {
AIChatBoxProps,
ChatColors,
ChatTheme,
Message,
} from "react-ai-chatkit";
const config: AIChatBoxProps = {
messages: [],
onSendMessage: (message: string) => console.log(message),
theme: "dark",
};
export default function App() {
return <AIChatBox {...config} />;
}🔗 Links
- 📖 GitHub
- 📦 npm
- 🐛 Report an issue
📄 License
MIT
