Reference / Components

CopilotChatMessageView

Component for rendering a list of chat messages

Overview

CopilotChatMessageView renders a list of chat messages and, optionally, a typing cursor while the agent is running. It delegates rendering of individual messages to slot components (assistantMessage and userMessage) and supports a render-prop children function for full control over layout.

Import

Props

isRunningboolean
Default: "false"

Whether the agent is currently executing. When true, the cursor slot is rendered after the last message to indicate ongoing activity.

messagesMessage[]
Default: "[]"

The array of chat messages to render. Each message object contains at minimum an id, role ("user" or "assistant"), and content.

children(props: { isRunning: boolean; messages: Message[]; messageElements: React.ReactElement[] }) => React.ReactElement

Optional render-prop function that receives the resolved state and pre-built message elements. When provided, the component calls this function instead of rendering the default message list layout. The callback receives isRunning (current running state), messages (the raw message array), and messageElements (an array of React elements built from the assistantMessage and userMessage slots).

Slots

All slot props follow the CopilotKit slot system: each accepts a replacement React component, a className string that is merged into the default component's classes, or a partial props object that extends the default component.

assistantMessageSlotProp<typeof CopilotChatAssistantMessage>

Slot for rendering assistant messages. Defaults to CopilotChatAssistantMessage, which provides Markdown rendering, tool call display, and an action toolbar.

As a replacement component:

<CopilotChatMessageView
  assistantMessage={({ message }) => (
    <div className="my-assistant-msg">{message.content}</div>
  )}
/>

As a className:

<CopilotChatMessageView assistantMessage="bg-blue-50 rounded-lg" />

As partial props:

<CopilotChatMessageView assistantMessage={{ toolbarVisible: false }} />
userMessageSlotProp<typeof CopilotChatUserMessage>

Slot for rendering user messages. Defaults to CopilotChatUserMessage, which provides right-aligned message display with optional branch navigation.

As a replacement component:

<CopilotChatMessageView
  userMessage={({ message }) => (
    <div className="my-user-msg">{message.content}</div>
  )}
/>

As a className:

<CopilotChatMessageView userMessage="bg-gray-100 rounded-lg" />
cursorSlotProp<typeof CopilotChatMessageView.Cursor>

Slot for the typing indicator displayed while isRunning is true. Defaults to CopilotChatMessageView.Cursor, which renders a pulsing dot animation.

As a replacement component:

<CopilotChatMessageView
  cursor={() => <span className="animate-bounce">...</span>}
/>

As a className:

<CopilotChatMessageView cursor="text-blue-500" />

Usage

Basic Message List

function MessageList() {
  const { agent } = useAgent();

  return (
    <CopilotChatMessageView
      messages={agent.messages}
      isRunning={agent.isRunning}
    />
  );
}

Customizing Message Slots

function CustomMessages() {
  const { agent } = useAgent();

  return (
    <CopilotChatMessageView
      messages={agent.messages}
      isRunning={agent.isRunning}
      assistantMessage="bg-blue-50 p-4 rounded-xl"
      userMessage="bg-gray-100 p-4 rounded-xl"
      cursor={() => (
        <div className="animate-pulse text-gray-400">Thinking...</div>
      )}
    />
  );
}

Render-Prop Children for Custom Layout

function CustomLayout() {
  const { agent } = useAgent();

  return (
    <CopilotChatMessageView
      messages={agent.messages}
      isRunning={agent.isRunning}
    >
      {({ isRunning, messages, messageElements }) => (
        <div className="flex flex-col gap-4 p-6">
          <div className="text-sm text-gray-500">
            {messages.length} message{messages.length !== 1 ? "s" : ""}
          </div>
          {messageElements}
          {isRunning && (
            <div className="text-sm text-blue-500 animate-pulse">
              Agent is responding...
            </div>
          )}
        </div>
      )}
    </CopilotChatMessageView>
  );
}

Hiding the Toolbar on Assistant Messages

function MinimalChat() {
  const { agent } = useAgent();

  return (
    <CopilotChatMessageView
      messages={agent.messages}
      isRunning={agent.isRunning}
      assistantMessage={{ toolbarVisible: false }}
    />
  );
}

Behavior

  • Message Rendering: Each message in the messages array is rendered using the corresponding slot component based on its role. Assistant messages use the assistantMessage slot; user messages use the userMessage slot.
  • Cursor Display: The cursor slot is only rendered when isRunning is true. It appears after the last message in the list.
  • Render-Prop Override: When children is provided as a function, the component delegates all layout to that function. The messageElements array is pre-built from the slot components, so custom layouts still benefit from slot customization.
  • Slot System: Each slot prop accepts three forms -- a replacement component, a className string merged into the default, or a partial props object that extends the default component's props.

Related