@copilotz/chat-ui 0.1.0 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,38 +1,430 @@
1
1
  # @copilotz/chat-ui
2
2
 
3
- Reusable Copilotz chat UI components (React + TypeScript).
3
+ **The chat interface your AI agent deserves.**
4
4
 
5
- ## Install
5
+ Chat UI libraries give you message bubbles. Your AI agent has tool calls, streaming responses, file uploads, audio recording, persistent threads, and user memories. This gives you everything else.
6
+
7
+ [![npm](https://img.shields.io/npm/v/@copilotz/chat-ui)](https://www.npmjs.com/package/@copilotz/chat-ui)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178c6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
9
+ [![React](https://img.shields.io/badge/React-18+-61dafb?logo=react&logoColor=white)](https://react.dev/)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
11
+
12
+ ---
13
+
14
+ ## The Problem
15
+
16
+ You're building a frontend for your AI agent. You grab a chat UI library. It renders messages. Great.
17
+
18
+ Then you need to show tool calls — the library doesn't support that. Streaming with a thinking indicator — you'll build it yourself. File uploads with previews — more custom code. Audio recording — even more. Thread management with search and archive — at this point you're maintaining your own chat UI.
19
+
20
+ **There's no shadcn for agentic chat. Just parts.**
21
+
22
+ ## The Solution
23
+
24
+ `@copilotz/chat-ui` is the complete chat interface for AI agents. Everything you need to ship a production chat experience, in one package:
25
+
26
+ | What You Need | What This Gives You |
27
+ |---------------|---------------------|
28
+ | Messages | Markdown with syntax highlighting, streaming with thinking indicator |
29
+ | Tool Calls | Expandable cards with args, results, status, and execution time |
30
+ | Media | Image/audio/video attachments with native playback controls |
31
+ | Input | File upload (drag & drop), audio recording, attachment previews |
32
+ | Threads | Sidebar with search, archive, date grouping, rename, delete |
33
+ | User Profile | Dynamic fields, memories (CRUD), agent vs user distinction |
34
+ | Customization | 50+ labels (i18n-ready), feature toggles, 4 presets, theming |
35
+
36
+ **One package. Backend-agnostic. Production-ready.**
37
+
38
+ ---
39
+
40
+ ## Quick Start
6
41
 
7
42
  ```bash
8
43
  npm install @copilotz/chat-ui
9
44
  ```
10
45
 
11
- ## Styles
46
+ Import the styles once in your app:
12
47
 
13
- This package ships a compiled stylesheet. Import it once in your app:
14
-
15
- ```ts
48
+ ```tsx
16
49
  import '@copilotz/chat-ui/styles.css';
17
50
  ```
18
51
 
19
- ## Usage
52
+ Drop in the component:
20
53
 
21
54
  ```tsx
22
- import { ChatUI, defaultChatConfig } from '@copilotz/chat-ui';
55
+ import { ChatUI } from '@copilotz/chat-ui';
56
+
57
+ function App() {
58
+ const [messages, setMessages] = useState([]);
23
59
 
24
- export function Example() {
25
60
  return (
26
61
  <ChatUI
27
- config={defaultChatConfig}
28
- user={{ id: 'user-1', name: 'User' }}
62
+ messages={messages}
63
+ user={{ id: 'user-1', name: 'Alex' }}
29
64
  assistant={{ name: 'Assistant' }}
30
65
  callbacks={{
31
66
  onSendMessage: (content, attachments) => {
32
- console.log(content, attachments);
33
- }
67
+ // Handle message — connect to your backend
68
+ },
34
69
  }}
35
70
  />
36
71
  );
37
72
  }
38
73
  ```
74
+
75
+ That's it. You have a full-featured chat interface.
76
+
77
+ ---
78
+
79
+ ## Features
80
+
81
+ ### Messages That Do More
82
+
83
+ Real-time streaming with a thinking indicator while waiting for the first token. Markdown rendering with syntax highlighting. Tool calls displayed as expandable cards showing name, arguments, result, and execution time.
84
+
85
+ ```tsx
86
+ const message = {
87
+ id: '1',
88
+ role: 'assistant',
89
+ content: 'Here is the chart you requested.',
90
+ timestamp: Date.now(),
91
+ isStreaming: false,
92
+ toolCalls: [{
93
+ id: 'tc-1',
94
+ name: 'generate_chart',
95
+ arguments: { type: 'bar', data: [1, 2, 3] },
96
+ result: { url: 'https://...' },
97
+ status: 'completed',
98
+ startTime: 1234567890,
99
+ endTime: 1234567891,
100
+ }],
101
+ attachments: [{
102
+ kind: 'image',
103
+ dataUrl: 'data:image/png;base64,...',
104
+ mimeType: 'image/png',
105
+ }],
106
+ };
107
+ ```
108
+
109
+ ### Input That Works
110
+
111
+ File uploads with drag & drop. Audio recording with built-in MediaRecorder. Attachment previews with playback controls. Upload progress indicators. Stop generation button during streaming.
112
+
113
+ ### Thread Management
114
+
115
+ Sidebar with threads grouped by date (Today, Yesterday, etc.). Search and filter. Archive toggle. Create, rename, and delete with confirmation dialogs. Collapsible icon mode for more screen space.
116
+
117
+ ### User Profile
118
+
119
+ Built-in sheet panel with user info, dynamic custom fields (auto-detects icons based on field names), and a memories section. Memories support CRUD operations and distinguish between agent-created and user-created entries.
120
+
121
+ ### Agent Selector
122
+
123
+ ChatGPT-style dropdown for switching between multiple agents. Displays agent avatars, names, and descriptions (truncated for long text). Consecutive messages from the same sender are automatically grouped to save screen space.
124
+
125
+ ```tsx
126
+ const agents = [
127
+ { id: 'assistant', name: 'Assistant', description: 'General purpose helper' },
128
+ { id: 'coder', name: 'Code Expert', description: 'Specialized in programming', avatarUrl: '/coder.png' },
129
+ ];
130
+
131
+ <ChatUI
132
+ agentOptions={agents}
133
+ selectedAgentId="assistant"
134
+ onSelectAgent={(agentId) => setSelectedAgent(agentId)}
135
+ // ... other props
136
+ />
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Configuration
142
+
143
+ The configuration system lets you customize everything without touching the component internals.
144
+
145
+ ### Presets
146
+
147
+ Start with a preset and override what you need:
148
+
149
+ ```tsx
150
+ import { ChatUI, chatConfigPresets } from '@copilotz/chat-ui';
151
+
152
+ // Minimal: no threads, no file upload, compact mode
153
+ <ChatUI config={chatConfigPresets.minimal} />
154
+
155
+ // Full: all features enabled, timestamps, word count
156
+ <ChatUI config={chatConfigPresets.full} />
157
+
158
+ // Developer: tool calls visible, timestamps, file upload
159
+ <ChatUI config={chatConfigPresets.developer} />
160
+
161
+ // Customer Support: threads, file upload, no message editing
162
+ <ChatUI config={chatConfigPresets.customer_support} />
163
+ ```
164
+
165
+ ### Custom Configuration
166
+
167
+ ```tsx
168
+ <ChatUI
169
+ config={{
170
+ branding: {
171
+ title: 'Acme Assistant',
172
+ subtitle: 'How can I help you today?',
173
+ logo: <AcmeLogo />,
174
+ avatar: <BotIcon />,
175
+ },
176
+ labels: {
177
+ inputPlaceholder: 'Ask me anything...',
178
+ sendButton: 'Send',
179
+ newChat: 'New Conversation',
180
+ thinking: 'Thinking...',
181
+ toolUsed: 'Tool Used',
182
+ // ... 50+ customizable labels for full i18n
183
+ },
184
+ features: {
185
+ enableThreads: true,
186
+ enableFileUpload: true,
187
+ enableAudioRecording: true,
188
+ enableMessageEditing: true,
189
+ enableMessageCopy: true,
190
+ enableRegeneration: true,
191
+ enableToolCallsDisplay: true,
192
+ maxAttachments: 4,
193
+ maxFileSize: 10 * 1024 * 1024, // 10MB
194
+ },
195
+ ui: {
196
+ theme: 'auto', // 'light' | 'dark' | 'auto'
197
+ showTimestamps: true,
198
+ showAvatars: true,
199
+ compactMode: false,
200
+ },
201
+ }}
202
+ />
203
+ ```
204
+
205
+ ### Custom Right Sidebar
206
+
207
+ Add a custom component to the right sidebar (e.g., profile info, settings, context):
208
+
209
+ ```tsx
210
+ <ChatUI
211
+ config={{
212
+ customComponent: {
213
+ label: 'Profile',
214
+ icon: <User />,
215
+ component: ({ onClose, isMobile }) => (
216
+ <div className="p-4">
217
+ <h2>User Profile</h2>
218
+ <button onClick={onClose}>Close</button>
219
+ </div>
220
+ ),
221
+ },
222
+ }}
223
+ />
224
+ ```
225
+
226
+ ---
227
+
228
+ ## Callbacks
229
+
230
+ All user interactions are handled through callbacks. This keeps the component purely presentational — you control the data.
231
+
232
+ ```tsx
233
+ <ChatUI
234
+ callbacks={{
235
+ // Messages
236
+ onSendMessage: (content, attachments, stateCallback) => {},
237
+ onEditMessage: (messageId, newContent, stateCallback) => {},
238
+ onDeleteMessage: (messageId, stateCallback) => {},
239
+ onRegenerateMessage: (messageId, stateCallback) => {},
240
+ onCopyMessage: (messageId, content, stateCallback) => {},
241
+ onStopGeneration: (stateCallback) => {},
242
+
243
+ // Threads
244
+ onCreateThread: (title, stateCallback) => {},
245
+ onSelectThread: (threadId, stateCallback) => {},
246
+ onRenameThread: (threadId, newTitle, stateCallback) => {},
247
+ onDeleteThread: (threadId, stateCallback) => {},
248
+ onArchiveThread: (threadId, stateCallback) => {},
249
+
250
+ // User Menu
251
+ onViewProfile: () => {},
252
+ onOpenSettings: () => {},
253
+ onThemeChange: (theme) => {}, // 'light' | 'dark' | 'system'
254
+ onLogout: () => {},
255
+ }}
256
+ />
257
+ ```
258
+
259
+ ---
260
+
261
+ ## Props Reference
262
+
263
+ ### ChatUI
264
+
265
+ | Prop | Type | Description |
266
+ |------|------|-------------|
267
+ | `messages` | `ChatMessage[]` | Array of messages to display |
268
+ | `threads` | `ChatThread[]` | Array of conversation threads |
269
+ | `currentThreadId` | `string \| null` | Currently selected thread ID |
270
+ | `config` | `ChatConfig` | Configuration object |
271
+ | `callbacks` | `ChatCallbacks` | Event handlers |
272
+ | `isGenerating` | `boolean` | Whether the assistant is generating a response |
273
+ | `user` | `{ id, name?, avatar?, email? }` | Current user info |
274
+ | `assistant` | `{ name?, avatar?, description? }` | Assistant info |
275
+ | `suggestions` | `string[]` | Suggested prompts shown when no messages |
276
+ | `agentOptions` | `AgentOption[]` | Available agents for the selector dropdown |
277
+ | `selectedAgentId` | `string \| null` | Currently selected agent ID |
278
+ | `onSelectAgent` | `(agentId: string) => void` | Called when user selects an agent |
279
+ | `initialInput` | `string` | Pre-fill the input field (e.g., from URL params) |
280
+ | `onInitialInputConsumed` | `() => void` | Called when initial input is modified/sent |
281
+ | `className` | `string` | Additional CSS classes |
282
+
283
+ ### ChatMessage
284
+
285
+ ```typescript
286
+ interface ChatMessage {
287
+ id: string;
288
+ role: 'user' | 'assistant' | 'system';
289
+ content: string;
290
+ timestamp: number;
291
+ attachments?: MediaAttachment[];
292
+ isStreaming?: boolean;
293
+ isComplete?: boolean;
294
+ isEdited?: boolean;
295
+ toolCalls?: ToolCall[];
296
+ metadata?: Record<string, any>;
297
+ }
298
+ ```
299
+
300
+ ### MediaAttachment
301
+
302
+ ```typescript
303
+ type MediaAttachment =
304
+ | { kind: 'image'; dataUrl: string; mimeType: string; fileName?: string }
305
+ | { kind: 'audio'; dataUrl: string; mimeType: string; durationMs?: number }
306
+ | { kind: 'video'; dataUrl: string; mimeType: string; poster?: string };
307
+ ```
308
+
309
+ ### ToolCall
310
+
311
+ ```typescript
312
+ interface ToolCall {
313
+ id: string;
314
+ name: string;
315
+ arguments: Record<string, any>;
316
+ result?: any;
317
+ status: 'pending' | 'running' | 'completed' | 'failed';
318
+ startTime?: number;
319
+ endTime?: number;
320
+ }
321
+ ```
322
+
323
+ ### AgentOption
324
+
325
+ ```typescript
326
+ interface AgentOption {
327
+ id: string;
328
+ name: string;
329
+ description?: string; // Shown in dropdown (truncated to 2 lines)
330
+ avatarUrl?: string; // Agent avatar image
331
+ }
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Exports
337
+
338
+ ```tsx
339
+ // Components
340
+ export { ChatUI } from './components/chat/ChatUI';
341
+ export { ChatHeader } from './components/chat/ChatHeader';
342
+ export { ChatInput } from './components/chat/ChatInput';
343
+ export { Message } from './components/chat/Message';
344
+ export { Sidebar } from './components/chat/Sidebar';
345
+ export { ThreadManager } from './components/chat/ThreadManager';
346
+ export { UserProfile } from './components/chat/UserProfile';
347
+ export { UserMenu } from './components/chat/UserMenu';
348
+ export { ChatUserContextProvider, useChatUserContext } from './components/chat/UserContext';
349
+
350
+ // Configuration
351
+ export { defaultChatConfig, mergeConfig, chatConfigPresets, validateConfig } from './config/chatConfig';
352
+ export { themeUtils, featureFlags, configUtils } from './config/chatConfig';
353
+
354
+ // Types
355
+ export type { ChatMessage, ChatThread, ChatConfig, ChatCallbacks } from './types/chatTypes';
356
+ export type { MediaAttachment, ToolCall, ChatState, ChatUserContext, MemoryItem } from './types/chatTypes';
357
+
358
+ // Utilities
359
+ export { cn } from './lib/utils';
360
+ ```
361
+
362
+ ---
363
+
364
+ ## Styling
365
+
366
+ The package ships with compiled CSS that includes all necessary styles. Import it once:
367
+
368
+ ```tsx
369
+ import '@copilotz/chat-ui/styles.css';
370
+ ```
371
+
372
+ ### Theming
373
+
374
+ The component respects the `dark` class on your document root. Set theme programmatically:
375
+
376
+ ```tsx
377
+ import { themeUtils } from '@copilotz/chat-ui';
378
+
379
+ // Apply theme
380
+ themeUtils.applyTheme('dark'); // or 'light' or 'auto'
381
+
382
+ // Get system preference
383
+ const systemTheme = themeUtils.getSystemTheme(); // 'light' | 'dark'
384
+ ```
385
+
386
+ ### CSS Variables
387
+
388
+ Override CSS variables to customize colors (uses Tailwind/shadcn conventions):
389
+
390
+ ```css
391
+ :root {
392
+ --background: 0 0% 100%;
393
+ --foreground: 222.2 84% 4.9%;
394
+ --primary: 222.2 47.4% 11.2%;
395
+ --primary-foreground: 210 40% 98%;
396
+ /* ... */
397
+ }
398
+ ```
399
+
400
+ ---
401
+
402
+ ## Requirements
403
+
404
+ - React 18+
405
+ - Tailwind CSS 4+ (for custom styling, optional)
406
+
407
+ ---
408
+
409
+ ## Works With Any Backend
410
+
411
+ This package is purely presentational. It doesn't make API calls or manage state. You provide the data, it renders the UI.
412
+
413
+ Works with:
414
+ - **Copilotz** — use `@copilotz/chat-adapter` for seamless integration
415
+ - **OpenAI** — connect to the Chat Completions API
416
+ - **Anthropic** — connect to Claude
417
+ - **LangChain** — use with any LangChain backend
418
+ - **Custom backends** — any API that returns messages
419
+
420
+ ---
421
+
422
+ ## License
423
+
424
+ MIT — see [LICENSE](./LICENSE)
425
+
426
+ ---
427
+
428
+ <p align="center">
429
+ <strong>Ship your agent's interface, not your UI backlog.</strong>
430
+ </p>