Skip to content

wu-changxing/chat-ui

Repository files navigation

chat-ui

Copy-paste chat UI components for React. Own your code.

Inspired by shadcn/ui - this is NOT a component library you install as a dependency. Instead, you copy the source code into your project and customize it however you want.

Why?

  • You own the code - No npm dependency, no version conflicts
  • Full customization - Change anything you want
  • Learn by reading - The code is right there
  • No lock-in - It's just React + Tailwind

Quick Start

1. Add components to your project

npx @connectonion/chat-ui add

This copies 10 files to ./components/chat/:

  • chat.tsx - Main chat component with empty state
  • chat-message.tsx - Single message with avatar
  • chat-messages.tsx - Scrollable message list
  • chat-input.tsx - Auto-resizing textarea input
  • chat-typing.tsx - Typing indicator animation
  • chat-empty-state.tsx - Welcome screen with suggestions
  • use-chat.ts - State management hook
  • types.ts - TypeScript types
  • utils.ts - cn() utility function
  • index.ts - Exports

2. Install peer dependencies

npm install clsx tailwind-merge

3. Use the components

'use client'

import { Chat, useChat } from '@/components/chat'

export default function ChatPage() {
  const { messages, isLoading, send } = useChat({
    onSend: async (message) => {
      const response = await fetch('/api/chat', {
        method: 'POST',
        body: JSON.stringify({ message }),
      })
      const data = await response.json()
      return data.reply
    },
  })

  return (
    <main className="h-screen">
      <Chat
        messages={messages}
        onSend={send}
        isLoading={isLoading}
      />
    </main>
  )
}

Components

<Chat>

The all-in-one chat component. Shows empty state when no messages, typing indicator when loading.

<Chat
  messages={messages}                    // Message[]
  onSend={send}                          // (message: string) => void
  isLoading={isLoading}                  // Shows typing indicator
  placeholder="Send a message..."        // Input placeholder
  emptyStateTitle="How can I help?"      // Empty state heading
  emptyStateDescription="Ask anything"   // Empty state description
  suggestions={['Hello', 'Help me']}     // Suggestion buttons
/>

<ChatEmptyState>

Welcome screen shown when there are no messages.

<ChatEmptyState
  title="How can I help you?"
  description="Ask me anything"
  suggestions={['Write code', 'Debug', 'Explain']}
  onSuggestionClick={(text) => send(text)}
/>

<ChatMessage>

A single message with avatar and role label.

<ChatMessage
  message={{
    id: '1',
    role: 'assistant',
    content: 'Hello! How can I help?',
  }}
/>

<ChatInput>

Auto-resizing textarea with send button.

<ChatInput
  onSend={(message) => console.log(message)}
  isLoading={false}
  placeholder="Type a message..."
  hint="Press Enter to send"
/>

<ChatTyping>

Animated typing indicator.

{isLoading && <ChatTyping />}

useChat Hook

State management for chat.

const {
  messages,    // Message[]
  isLoading,   // boolean
  send,        // (content: string) => Promise<void>
  addMessage,  // (message: Omit<Message, 'id'>) => void
  setMessages, // React setState
  clear,       // () => void
} = useChat({
  initialMessages: [],
  onSend: async (message, messages) => {
    // Return the assistant's response
    return 'Hello!'
  },
})

Types

interface Message {
  id: string
  role: 'user' | 'assistant' | 'system'
  content: string
  createdAt?: Date
}

Customization

Styling

Components use Tailwind CSS. Edit the files directly:

// components/chat/chat-message.tsx

// Change avatar gradient
<div className="bg-gradient-to-br from-blue-500 to-cyan-500">

Layout

Compose the primitives however you want:

<div className="flex h-screen">
  <Sidebar />
  <main className="flex-1">
    <Header />
    <ChatMessages messages={messages} />
    <ChatInput onSend={send} />
  </main>
</div>

Add features

The code is yours. Add whatever you need:

  • Markdown rendering
  • Code syntax highlighting
  • File uploads
  • Message actions (copy, regenerate)
  • Streaming responses

CLI

npx @connectonion/chat-ui add                          # Add to ./components/chat
npx @connectonion/chat-ui add --path ./src/chat        # Custom path
npx @connectonion/chat-ui add --force                  # Overwrite existing
npx @connectonion/chat-ui list                         # List components
npx @connectonion/chat-ui help                         # Show help

Requirements

  • React 18+
  • Tailwind CSS 3+
  • Node.js 16+

Philosophy

This project follows the shadcn/ui philosophy:

"Copy and paste components directly into your app and customize them. You decide how things are built."

Chat interfaces are highly customized per application. Instead of fighting with a library's API, just own the code and modify it.

License

MIT

About

Copy-paste chat UI components for React. Inspired by shadcn/ui.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors