A complete, production-ready chat interface component for AI conversations.

Overview

The ChatInterface component provides:

  • Message history display
  • Input field with send button
  • Streaming support
  • Error handling
  • Loading states
  • Responsive design

Basic Usage

import ChatInterface from "@/components/ai/ChatInterface";
import type { ChatMessageProps } from "@/components/ai/ChatMessage";

export default function ChatPage() {
  const [messages, setMessages] = useState<ChatMessageProps[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [isTyping, setIsTyping] = useState(false);

  const handleSendMessage = async (message: string) => {
    // Your message sending logic
    setIsLoading(true);
    // ... send to API
    setIsLoading(false);
  };

  return (
    <div className="min-h-screen p-4">
      <ChatInterface
        messages={messages}
        isLoading={isLoading}
        isTyping={isTyping}
        onSendMessage={handleSendMessage}
      />
    </div>
  );
}

Props

interface ChatInterfaceProps {
  messages: ChatMessageProps[];  // Required: Array of messages to display
  isLoading?: boolean;          // Show loading state on send button
  isTyping?: boolean;           // Show typing indicator
  disabled?: boolean;            // Disable input (e.g., no subscription)
  placeholder?: string;          // Input placeholder text
  onSendMessage: (message: string) => void;  // Required: Handler for sending messages
  inputValue?: string;           // Controlled input value (optional)
  onInputChange?: (value: string) => void;  // Controlled input change handler (optional)
}

Examples

Basic Chat

const [messages, setMessages] = useState<ChatMessageProps[]>([]);

<ChatInterface
  messages={messages}
  onSendMessage={handleSendMessage}
/>

With Loading States

<ChatInterface
  messages={messages}
  isLoading={isSending}
  isTyping={isStreaming}
  onSendMessage={handleSendMessage}
/>

With Custom Placeholder

<ChatInterface
  messages={messages}
  placeholder="Ask your AI assistant..."
  onSendMessage={handleSendMessage}
/>

Disabled for Non-Subscribers

<ChatInterface
  messages={messages}
  disabled={!hasSubscription}
  placeholder={hasSubscription ? "Ask a question..." : "Upgrade to continue chatting"}
  onSendMessage={handleSendMessage}
/>

Controlled Input

const [inputValue, setInputValue] = useState("");

<ChatInterface
  messages={messages}
  inputValue={inputValue}
  onInputChange={setInputValue}
  onSendMessage={handleSendMessage}
/>

Integration with ChatSidebar

The component is designed to work with ChatSidebar:

import ChatSidebar from "@/components/ai/ChatSidebar";
import ChatInterface from "@/components/ai/ChatInterface";

export default function ChatPage() {
  return (
    <div className="flex h-screen">
      <ChatSidebar
        currentConversationId={conversationId}
        onSelectConversation={handleSelect}
        onNewConversation={handleNew}
      />
      <div className="flex-1">
        <ChatInterface
          messages={messages}
          isTyping={isTyping}
          onSendMessage={handleSend}
        />
      </div>
    </div>
  );
}

Message Format

Messages follow this structure:

interface Message {
  role: "user" | "assistant";
  content: string;
  timestamp?: Date;
  id?: string;
}

State Management

The component manages:

  • Message history
  • Input state
  • Loading state
  • Error state
  • Streaming state (if enabled)

Error Handling

The component handles:

  • Network errors
  • API errors
  • Authentication errors
  • Subscription access errors

Errors are displayed as user-friendly messages.

Accessibility

  • Keyboard navigation - Enter to send, Escape to cancel
  • Screen reader support - Proper ARIA labels
  • Focus management - Auto-focus on input
  • Error announcements - Accessible error messages

Best Practices

  1. Wrap in authenticated route - Ensure user is logged in
  2. Show subscription status - Display subscription status alongside chat
  3. Handle errors gracefully - Provide clear error messages
  4. Optimize for mobile - Test on mobile devices
  5. Limit message history - Prevent memory issues

Advanced Usage

Custom Message Renderer

const CustomMessage = ({ message }: { message: Message }) => {
  return (
    <div className={`message ${message.role}`}>
      <div className="avatar">
        <img src={message.role === "user" ? userAvatar : aiAvatar} />
      </div>
      <div className="content">{message.content}</div>
    </div>
  );
};

<ChatInterface
  messageRenderer={CustomMessage}
/>

Integration with State Management

import { useChatStore } from "@/store/chat";

export default function ChatPage() {
  const { messages, addMessage } = useChatStore();

  return (
    <ChatInterface
      initialMessages={messages}
      onMessageSent={(msg) => addMessage({ role: "user", content: msg })}
    />
  );
}

Next Steps