@aichatkit/ui
v0.0.0-alpha.6
Published
Composable chat UI components for AI powered apps
Maintainers
Readme
@aichatkit/ui
React components for building chat interfaces with Hypermode ChatKit and rich response items.
Installation
npm install @aichatkit/uiQuick Start
import "@aichatkit/ui/dist/base.css"
import { ChatInterface, Avatar } from "@aichatkit/ui"
import { ApolloAdapter } from "@aichatkit/apollo-adapter"
import { LocalStorageAdapter } from "@aichatkit/localstorage-adapter"
import { SendIcon, PlusIcon, XIcon } from "lucide-react"
// Initialize adapters
const networkAdapter = new ApolloAdapter({
apiUrl: "https://your-api.com/graphql",
})
const storageAdapter = new LocalStorageAdapter()
await storageAdapter.initialize()
// Connect storage with network for syncing
storageAdapter.setNetworkCallbacks({
getConversationItems: (agentId) => networkAdapter.getConversationItems(agentId),
clearConversationHistory: (agentId) => networkAdapter.clearConversationHistory(agentId),
})
// Use the chat interface
function ChatApp() {
return (
<ChatInterface
networkAdapter={networkAdapter}
storageAdapter={storageAdapter}
hypermodeStyle={true}
sendButtonIcon={<SendIcon size={18} />}
newConversationIcon={<PlusIcon size={18} />}
deleteConversationIcon={<XIcon size={16} />}
userAvatar={<Avatar initial="U" role="user" hypermodeStyle={true} />}
assistantAvatar={<Avatar initial="A" hypermodeStyle={true} />}
onCardAction={(action) => {
// Handle card button clicks
console.log("Card action:", action)
}}
/>
)
}Components
Main Components
ChatInterface
Complete chat interface with messages, input, sidebar, and rich response items.
interface ChatInterfaceProps {
networkAdapter?: NetworkAdapter
storageAdapter?: StorageAdapter
showSidebar?: boolean
className?: string
chatAreaClassName?: string
sidebarClassName?: string
inputAreaClassName?: string
headerClassName?: string
headerContent?: ReactNode
sidebarHeaderContent?: ReactNode
userProfileContent?: ReactNode
username?: string
inputPlaceholder?: string
sendButtonIcon?: ReactNode
newConversationIcon?: ReactNode
deleteConversationIcon?: ReactNode
hypermodeStyle?: boolean
userAvatar?: ReactNode
assistantAvatar?: ReactNode
onCardAction?: (action: CardAction) => void
}ResponseItem
Displays different types of response items including messages, tool calls, and cards.
<ResponseItem
item={{
id: "tool_1",
type: "tool_call",
toolCall: {
id: "call_1",
name: "get_weather",
arguments: { location: "NYC" },
status: "completed",
result: { temperature: "22°C" },
},
}}
hypermodeStyle={true}
/>ChatBubble
Individual message bubble component.
<ChatBubble
content="Hello world!"
role="user"
timestamp={new Date()}
hypermodeStyle={true}
avatar={<Avatar initial="U" role="user" />}
/>ToolCallDisplay
Displays tool execution with status, arguments, and results.
<ToolCallDisplay
toolCall={{
id: "call_1",
name: "get_weather",
arguments: { location: "New York" },
status: "completed",
result: { temperature: "22°C", condition: "Sunny" },
}}
hypermodeStyle={true}
/>CardDisplay
Rich content cards with structured data and interactive actions.
<CardDisplay
card={{
id: "weather_card",
type: "weather",
title: "Weather Information",
content: { location: "New York", temperature: "22°C" },
actions: [
{
id: "forecast",
label: "View Forecast",
type: "button",
action: "show_forecast",
},
],
}}
onAction={(action) => console.log("Action:", action)}
hypermodeStyle={true}
/>ChatSidebar
Sidebar for displaying and managing conversations.
<ChatSidebar
conversations={conversations}
currentConversationId={currentId}
onCreateConversation={handleCreate}
onDeleteConversation={handleDelete}
onSelectConversation={handleSelect}
username="User"
hypermodeStyle={true}
/>LoadingIndicator
Loading animation for messages and processing states.
<LoadingIndicator dots={3} />
<LoadingChatBubble hypermodeStyle={true} />UI Components
Avatar
User or assistant avatar component.
<Avatar initial="U" role="user" size="md" hypermodeStyle={true} />Props:
initial: String - The initial to displayrole: 'user' | 'assistant' - The role of the usersize: 'sm' | 'md' | 'lg' - Size of the avatarhypermodeStyle: boolean - Whether to use Hypermode styling
Button
Reusable button component with variants.
<Button variant="primary" size="default" onClick={handleClick}>
Click me
</Button>Variants:
primary- Primary action buttonsecondary- Secondary action buttonghost- Minimal stylingdestructive- For dangerous actionswarning- Warning actions
Input
Text input field component.
<Input type="text" placeholder="Type a message..." value={value} onChange={handleChange} />Response Item Types
The UI components support various response item types:
Message Items
Standard chat messages between user and assistant.
{
id: "msg_123",
type: "message",
content: "Hello there!",
role: "assistant",
timestamp: "2024-01-01T00:00:00Z"
}Tool Call Items
Displays tool executions with arguments, status, and results.
{
id: "tool_123",
type: "tool_call",
toolCall: {
id: "call_123",
name: "get_weather",
arguments: { location: "New York" },
status: "completed",
result: { temperature: "22°C", condition: "Sunny" }
}
}Card Items
Rich content cards with structured data and actions.
{
id: "card_123",
type: "card",
card: {
id: "weather_card",
type: "weather",
title: "Weather Information",
content: { location: "New York", temperature: "22°C" },
actions: [
{
id: "view_forecast",
label: "View Forecast",
type: "button",
action: "show_forecast"
}
]
}
}Styling
The components support two styling modes:
1. Default Style
Clean, neutral design with light/dark mode support using CSS custom properties.
2. Hypermode Style
Dark mode with purple accents designed for AI applications.
Enable Hypermode styling by setting hypermodeStyle={true} on components:
<ChatInterface hypermodeStyle={true} />
<ChatBubble hypermodeStyle={true} />
<ToolCallDisplay hypermodeStyle={true} />
<CardDisplay hypermodeStyle={true} />
<Avatar hypermodeStyle={true} />CSS Import
Include the base styles in your application:
// Import styles directly
import "@aichatkit/ui/dist/base.css"
// Or use the path constant
import { CHATKIT_CSS_PATH } from "@aichatkit/ui"Tailwind CSS Integration
If using Tailwind CSS, add the component paths to your content configuration:
// tailwind.config.js
module.exports = {
content: [
// ... your content
"node_modules/@aichatkit/ui/dist/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
hypermode: {
bg: "#121212",
card: "#1c1c1c",
border: "#2a2a2a",
hover: "#282828",
input: "#222222",
accent: "#9333ea",
"accent-light": "#a855f7",
},
},
},
},
plugins: [],
}Advanced Usage
Custom Avatars
import { User, Bot } from "lucide-react"
;<ChatInterface
userAvatar={
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
<User size={16} className="text-white" />
</div>
}
assistantAvatar={
<div className="w-8 h-8 bg-purple-500 rounded-full flex items-center justify-center">
<Bot size={16} className="text-white" />
</div>
}
/>Custom Header
<ChatInterface
headerContent={
<div className="p-4 border-b flex items-center justify-between">
<h1>My AI Assistant</h1>
<button>Settings</button>
</div>
}
/>Card Action Handling
<ChatInterface
onCardAction={(action) => {
switch (action.action) {
case "show_forecast":
// Handle forecast action
showForecast(action.data?.location)
break
case "search_web":
// Handle web search
performSearch(action.data?.query)
break
default:
if (action.type === "link") {
window.open(action.action, "_blank")
}
}
}}
/>Custom Text Area
Replace the default input with a custom text area using the inputAreaContent prop:
<ChatInterface
networkAdapter={networkAdapter}
storageAdapter={storageAdapter}
inputAreaContent={(context) => (
<div className="border-t p-4 bg-white">
<div className="flex items-end gap-2">
<textarea
value={context.input}
onChange={(e) => context.setInput(e.target.value)}
placeholder={context.inputPlaceholder}
className="flex-1 max-h-32 min-h-[40px] resize-none rounded-lg border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
onKeyDown={(e) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault()
context.sendMessage(context.input)
context.setInput("")
}
}}
/>
<Button
onClick={() => {
context.sendMessage(context.input)
context.setInput("")
}}
disabled={context.loading || !context.input.trim()}
>
{context.sendButtonIcon}
</Button>
</div>
</div>
)}
/>Handling Different Response Items
import { ResponseItemList } from "@aichatkit/ui"
function CustomChatArea({ items }) {
return (
<ResponseItemList
items={items}
hypermodeStyle={true}
onCardAction={(action) => {
// Handle card actions
console.log("Card action:", action)
}}
userAvatar={<Avatar initial="U" role="user" hypermodeStyle={true} />}
assistantAvatar={<Avatar initial="A" hypermodeStyle={true} />}
/>
)
}TypeScript
The package includes comprehensive TypeScript definitions:
import type {
ChatResponseItem,
Message,
Conversation,
ChatInterfaceProps,
ToolCall,
Card,
CardAction,
} from "@aichatkit/ui"
const toolCall: ToolCall = {
id: "call_1",
name: "get_weather",
arguments: { location: "NYC" },
status: "completed",
result: { temperature: "22°C" },
}
const card: Card = {
id: "weather_card",
type: "weather",
title: "Weather Info",
content: { temperature: "22°C" },
actions: [
{
id: "forecast",
label: "View Forecast",
type: "button",
action: "show_forecast",
},
],
}
const conversation: Conversation = {
id: "conv-1",
title: "Chat with AI",
items: [
{
id: "msg_1",
type: "message",
content: "Hello",
role: "user",
},
{
id: "tool_1",
type: "tool_call",
toolCall: toolCall,
},
{
id: "card_1",
type: "card",
card: card,
},
],
}License
MIT © Hypermode
