or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

chat-components.mdcustomization.mddev-console.mdhooks.mdindex.mdmessage-components.mdtypes.md
README.mdVERIFICATION.md

message-components.mddocs/

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