0
# Message Components
1
2
Default and customizable components for rendering different message types in the chat interface. These components can be used as-is or replaced with custom implementations.
3
4
## Capabilities
5
6
### AssistantMessage
7
8
Default component for rendering AI assistant messages. Displays markdown content, handles loading states, and provides message controls.
9
10
```typescript { .api }
11
/**
12
* Default assistant message rendering component
13
* @param props - Assistant message configuration and callbacks
14
* @returns Rendered assistant message with controls
15
*/
16
function AssistantMessage(props: AssistantMessageProps): JSX.Element;
17
18
interface AssistantMessageProps {
19
/** The AI message content */
20
message?: AIMessage;
21
22
/** Whether this is the most recent message */
23
isCurrentMessage?: boolean;
24
25
/** Whether response is loading (thinking state) */
26
isLoading: boolean;
27
28
/** Whether response is actively streaming */
29
isGenerating: boolean;
30
31
/** Callback to regenerate this message */
32
onRegenerate?: () => void;
33
34
/** Callback when message is copied */
35
onCopy?: (message: string) => void;
36
37
/** Callback for positive feedback */
38
onThumbsUp?: (message: Message) => void;
39
40
/** Callback for negative feedback */
41
onThumbsDown?: (message: Message) => void;
42
43
/** Custom markdown component renderers */
44
markdownTagRenderers?: ComponentsMap;
45
46
/** Custom image renderer component */
47
ImageRenderer?: React.ComponentType<ImageRendererProps>;
48
49
/**
50
* @deprecated Use message property instead
51
* Note: Despite being deprecated, this property is currently REQUIRED
52
*/
53
rawData: any;
54
55
/** @deprecated Use message.generativeUI() instead */
56
subComponent?: React.JSX.Element;
57
}
58
59
interface AIMessage {
60
id: string;
61
role: "assistant";
62
content: string;
63
generativeUI?: () => React.ReactNode;
64
agentName?: string;
65
state?: any;
66
image?: ImageData;
67
}
68
```
69
70
**Usage Example:**
71
72
```typescript
73
import { AssistantMessage } from "@copilotkit/react-ui";
74
75
function CustomChat() {
76
const message = {
77
id: "msg-1",
78
role: "assistant" as const,
79
content: "Here's how to implement that feature:\n\n```typescript\nconst result = compute();\n```",
80
};
81
82
return (
83
<AssistantMessage
84
message={message}
85
rawData={message} // Required despite being deprecated
86
isCurrentMessage={true}
87
isLoading={false}
88
isGenerating={false}
89
onRegenerate={() => console.log("Regenerate")}
90
onCopy={(text) => navigator.clipboard.writeText(text)}
91
onThumbsUp={(msg) => console.log("Liked:", msg.id)}
92
onThumbsDown={(msg) => console.log("Disliked:", msg.id)}
93
/>
94
);
95
}
96
```
97
98
### UserMessage
99
100
Default component for rendering user messages. Handles both text messages and messages with image attachments.
101
102
```typescript { .api }
103
/**
104
* Default user message rendering component
105
* @param props - User message content and image renderer
106
* @returns Rendered user message
107
*/
108
function UserMessage(props: UserMessageProps): JSX.Element;
109
110
interface UserMessageProps {
111
/** The user message content */
112
message?: UserMessage;
113
114
/** Image renderer component for displaying attachments */
115
ImageRenderer: React.ComponentType<ImageRendererProps>;
116
117
/**
118
* @deprecated Use message property instead
119
* Note: Despite being deprecated, this property is currently REQUIRED
120
*/
121
rawData: any;
122
}
123
124
interface UserMessage {
125
id: string;
126
role: "user";
127
content: string;
128
image?: ImageData;
129
}
130
```
131
132
**Usage Example:**
133
134
```typescript
135
import { UserMessage, ImageRenderer } from "@copilotkit/react-ui";
136
137
function CustomChat() {
138
const message = {
139
id: "msg-2",
140
role: "user" as const,
141
content: "Can you help me with this diagram?",
142
image: {
143
format: "png",
144
bytes: "base64-encoded-image-data",
145
},
146
};
147
148
return (
149
<UserMessage
150
message={message}
151
rawData={message} // Required despite being deprecated
152
ImageRenderer={ImageRenderer}
153
/>
154
);
155
}
156
```
157
158
### ImageRenderer
159
160
Default component for rendering images in messages. Displays base64-encoded images with error handling.
161
162
```typescript { .api }
163
/**
164
* Default image rendering component
165
* @param props - Image data and optional text content
166
* @returns Rendered image element
167
*/
168
function ImageRenderer(props: ImageRendererProps): JSX.Element;
169
170
interface ImageRendererProps {
171
/** Image data with format and encoded bytes */
172
image: ImageData;
173
174
/** Optional text content to display with image */
175
content?: string;
176
177
/** Additional CSS class */
178
className?: string;
179
}
180
181
interface ImageData {
182
/** Image format (e.g., "png", "jpeg", "gif") */
183
format: string;
184
185
/** Base64-encoded image bytes */
186
bytes: string;
187
}
188
```
189
190
**Usage Example:**
191
192
```typescript
193
import { ImageRenderer } from "@copilotkit/react-ui";
194
195
function CustomImageDisplay() {
196
const imageData = {
197
format: "png",
198
bytes: "iVBORw0KGgoAAAANSUhEUgAAAAUA...", // base64 data
199
};
200
201
return (
202
<ImageRenderer
203
image={imageData}
204
content="Screenshot of the error"
205
className="my-custom-image"
206
/>
207
);
208
}
209
```
210
211
### Markdown
212
213
Markdown rendering component using react-markdown with support for GitHub Flavored Markdown, math equations, and custom renderers.
214
215
```typescript { .api }
216
/**
217
* Markdown rendering component with GFM and math support
218
* @param props - Markdown content and custom component renderers
219
* @returns Rendered markdown content
220
*/
221
function Markdown(props: MarkdownProps): JSX.Element;
222
223
interface MarkdownProps {
224
/** Markdown content string to render */
225
content: string;
226
227
/** Custom component renderers for markdown elements */
228
components?: ComponentsMap;
229
}
230
231
type ComponentsMap<T extends Record<string, object> = Record<string, object>> = {
232
[K in keyof T]: React.FC<{ children?: React.ReactNode } & T[K]>;
233
};
234
```
235
236
**Usage Example:**
237
238
```typescript
239
import { Markdown } from "@copilotkit/react-ui";
240
241
function CustomMarkdownDisplay() {
242
const content = `
243
# Title
244
245
Here's some **bold** and *italic* text.
246
247
\`\`\`typescript
248
const greeting = "Hello, World!";
249
console.log(greeting);
250
\`\`\`
251
252
- List item 1
253
- List item 2
254
255
| Column 1 | Column 2 |
256
|----------|----------|
257
| Data 1 | Data 2 |
258
`;
259
260
return (
261
<Markdown
262
content={content}
263
components={{
264
h1: ({ children }) => (
265
<h1 className="custom-heading">{children}</h1>
266
),
267
code: ({ children }) => (
268
<code className="custom-code">{children}</code>
269
),
270
}}
271
/>
272
);
273
}
274
```
275
276
### Custom Message Renderers
277
278
Props interfaces for creating fully custom message rendering components.
279
280
```typescript { .api }
281
interface RenderMessageProps {
282
/** The message to render */
283
message: Message;
284
285
/** Whether chat is currently in progress */
286
inProgress: boolean;
287
288
/** Message index in the array */
289
index: number;
290
291
/** Whether this is the most recent message */
292
isCurrentMessage: boolean;
293
294
/** Result from action execution if applicable */
295
actionResult?: string;
296
297
/** Assistant message component to use */
298
AssistantMessage?: React.ComponentType<AssistantMessageProps>;
299
300
/** User message component to use */
301
UserMessage?: React.ComponentType<UserMessageProps>;
302
303
/** Image renderer component to use */
304
ImageRenderer?: React.ComponentType<ImageRendererProps>;
305
306
/** Callback to regenerate message */
307
onRegenerate?: (messageId: string) => void;
308
309
/** Callback when message is copied */
310
onCopy?: (message: string) => void;
311
312
/** Callback for positive feedback */
313
onThumbsUp?: (message: Message) => void;
314
315
/** Callback for negative feedback */
316
onThumbsDown?: (message: Message) => void;
317
318
/** Custom markdown renderers */
319
markdownTagRenderers?: ComponentsMap;
320
}
321
322
type Message = AIMessage | UserMessage;
323
```
324
325
**Usage Example:**
326
327
```typescript
328
import { CopilotChat } from "@copilotkit/react-ui";
329
import type { RenderMessageProps } from "@copilotkit/react-ui";
330
331
function CustomMessageRenderer({
332
message,
333
isCurrentMessage,
334
AssistantMessage,
335
UserMessage,
336
ImageRenderer,
337
...props
338
}: RenderMessageProps) {
339
// Add custom wrapper or logic
340
return (
341
<div className="custom-message-wrapper">
342
<div className="message-metadata">
343
<span>{new Date(message.timestamp).toLocaleTimeString()}</span>
344
</div>
345
{message.role === "assistant" && AssistantMessage && (
346
<AssistantMessage
347
message={message}
348
rawData={message} // Required despite being deprecated
349
isCurrentMessage={isCurrentMessage}
350
ImageRenderer={ImageRenderer}
351
{...props}
352
/>
353
)}
354
{message.role === "user" && UserMessage && (
355
<UserMessage
356
message={message}
357
rawData={message} // Required despite being deprecated
358
ImageRenderer={ImageRenderer}
359
/>
360
)}
361
</div>
362
);
363
}
364
365
function App() {
366
return (
367
<CopilotChat
368
RenderMessage={CustomMessageRenderer}
369
/>
370
);
371
}
372
```
373
374
### Error Message Component
375
376
Interface for rendering error messages in the chat.
377
378
```typescript { .api }
379
interface ErrorMessageProps {
380
/** Error information */
381
error: ChatError;
382
383
/** Whether this is the most recent message */
384
isCurrentMessage?: boolean;
385
386
/** Callback to regenerate/retry */
387
onRegenerate?: () => void;
388
389
/** Callback when error is copied */
390
onCopy?: (message: string) => void;
391
}
392
393
interface ChatError {
394
/** Error message text */
395
message: string;
396
397
/** Operation that caused the error */
398
operation?: string;
399
400
/** Error timestamp */
401
timestamp: number;
402
}
403
```
404
405
**Usage Example:**
406
407
```typescript
408
import { CopilotChat } from "@copilotkit/react-ui";
409
import type { ErrorMessageProps } from "@copilotkit/react-ui";
410
411
function CustomErrorMessage({
412
error,
413
onRegenerate,
414
}: ErrorMessageProps) {
415
return (
416
<div className="custom-error">
417
<div className="error-icon">⚠️</div>
418
<div className="error-content">
419
<h4>Something went wrong</h4>
420
<p>{error.message}</p>
421
{error.operation && <small>During: {error.operation}</small>}
422
</div>
423
<button onClick={onRegenerate}>Retry</button>
424
</div>
425
);
426
}
427
428
function App() {
429
return (
430
<CopilotChat
431
ErrorMessage={CustomErrorMessage}
432
/>
433
);
434
}
435
```
436
437
### Suggestions Components
438
439
Components for rendering chat suggestions.
440
441
```typescript { .api }
442
/**
443
* Default suggestions list renderer
444
* @param props - Suggestions array and click handler
445
* @returns Rendered suggestions list
446
*/
447
function RenderSuggestionsList(props: RenderSuggestionsListProps): JSX.Element;
448
449
interface RenderSuggestionsListProps {
450
/** Array of suggestion items */
451
suggestions: CopilotChatSuggestion[];
452
453
/** Click handler for suggestions */
454
onSuggestionClick: (message: string) => void;
455
}
456
457
interface CopilotChatSuggestion {
458
/** Suggestion title/text displayed to user */
459
title: string;
460
461
/** Message to send when suggestion is clicked */
462
message: string;
463
464
/** Whether suggestion is still being generated */
465
partial?: boolean;
466
467
/** Optional CSS class */
468
className?: string;
469
}
470
```
471
472
**Usage Example:**
473
474
```typescript
475
import { CopilotChat } from "@copilotkit/react-ui";
476
import type { RenderSuggestionsListProps } from "@copilotkit/react-ui";
477
478
function CustomSuggestionsList({
479
suggestions,
480
onSuggestionClick,
481
}: RenderSuggestionsListProps) {
482
return (
483
<div className="custom-suggestions">
484
<h4>Try asking:</h4>
485
<div className="suggestion-grid">
486
{suggestions.map((suggestion, i) => (
487
<button
488
key={i}
489
onClick={() => onSuggestionClick(suggestion.message)}
490
disabled={suggestion.partial}
491
className={suggestion.className}
492
>
493
{suggestion.title}
494
{suggestion.partial && " ..."}
495
</button>
496
))}
497
</div>
498
</div>
499
);
500
}
501
502
function App() {
503
return (
504
<CopilotChat
505
suggestions={[
506
{ title: "Analyze data", message: "Can you analyze my dataset?" },
507
{ title: "Generate report", message: "Generate a summary report" },
508
{ title: "Export results", message: "How do I export the results?" },
509
]}
510
RenderSuggestionsList={CustomSuggestionsList}
511
/>
512
);
513
}
514
```
515
516
### RenderSuggestion
517
518
Individual suggestion button component. Exported for advanced customization when building custom suggestion lists.
519
520
**Note:** This component is exported as `RenderSuggestion` from the package (the internal component is named `Suggestion` but exported with the alias `RenderSuggestion`).
521
522
```typescript { .api }
523
/**
524
* Individual suggestion button component
525
* @param props - Suggestion data and click handler
526
* @returns Rendered suggestion button
527
*/
528
function RenderSuggestion(props: SuggestionProps): JSX.Element | null;
529
530
interface SuggestionProps {
531
/** Suggestion title to display */
532
title: string;
533
534
/** Message to send when clicked */
535
message: string;
536
537
/** Whether suggestion is still loading */
538
partial?: boolean;
539
540
/** Optional CSS class */
541
className?: string;
542
543
/** Click handler */
544
onClick: () => void;
545
}
546
```
547
548
**Usage Example:**
549
550
```typescript
551
import { RenderSuggestion } from "@copilotkit/react-ui";
552
import type { RenderSuggestionsListProps } from "@copilotkit/react-ui";
553
554
function CustomSuggestionsList({
555
suggestions,
556
onSuggestionClick,
557
}: RenderSuggestionsListProps) {
558
return (
559
<div className="custom-suggestions-layout">
560
{suggestions.map((suggestion, index) => (
561
<RenderSuggestion
562
key={index}
563
title={suggestion.title}
564
message={suggestion.message}
565
partial={suggestion.partial}
566
className={suggestion.className}
567
onClick={() => onSuggestionClick(suggestion.message)}
568
/>
569
))}
570
</div>
571
);
572
}
573
```
574
575
### Messages Container Component
576
577
Interface for customizing the messages container that wraps all messages.
578
579
```typescript { .api }
580
interface MessagesProps {
581
/** Array of all messages */
582
messages: Message[];
583
584
/** Whether chat is in progress */
585
inProgress: boolean;
586
587
/** Child elements (typically suggestions) */
588
children?: React.ReactNode;
589
590
/** Current chat error if any */
591
chatError?: ChatError | null;
592
593
/** Assistant message component */
594
AssistantMessage: React.ComponentType<AssistantMessageProps>;
595
596
/** User message component */
597
UserMessage: React.ComponentType<UserMessageProps>;
598
599
/** Error message component */
600
ErrorMessage?: React.ComponentType<ErrorMessageProps>;
601
602
/** Message renderer */
603
RenderMessage: React.ComponentType<RenderMessageProps>;
604
605
/** Image renderer */
606
ImageRenderer: React.ComponentType<ImageRendererProps>;
607
608
/** Regenerate callback */
609
onRegenerate?: (messageId: string) => void;
610
611
/** Copy callback */
612
onCopy?: (message: string) => void;
613
614
/** Thumbs up callback */
615
onThumbsUp?: (message: Message) => void;
616
617
/** Thumbs down callback */
618
onThumbsDown?: (message: Message) => void;
619
620
/** Custom markdown renderers */
621
markdownTagRenderers?: ComponentsMap;
622
}
623
```
624
625
### Input Component
626
627
Interface for customizing the chat input component.
628
629
```typescript { .api }
630
interface InputProps {
631
/** Whether chat is in progress */
632
inProgress: boolean;
633
634
/** Handler for sending messages */
635
onSend: (text: string) => Promise<Message>;
636
637
/** Whether input is visible */
638
isVisible?: boolean;
639
640
/** Stop generation handler */
641
onStop?: () => void;
642
643
/** Upload handler (file picker trigger) */
644
onUpload?: () => void;
645
646
/** Hide stop button */
647
hideStopButton?: boolean;
648
}
649
```
650