Chat

Pre-built chat component

Drop-in chat UI with streaming, markdown rendering, and tool execution display.


Basic Usage

import { CopilotChat } from '@yourgpt/copilot-sdk/ui';

function App() {
  return (
    <CopilotChat
      className="h-[600px] border rounded-xl"
    />
  );
}

Props

PropTypeDescription
titlestringHeader title
placeholderstringInput placeholder text
suggestionsstring[]Quick suggestion chips
classNamestringContainer class
toolRenderersRecord<string, Component>Custom tool result renderers

With Suggestions

<CopilotChat
  title="AI Assistant"
  placeholder="Ask me anything..."
  suggestions={[
    "What can you help me with?",
    "Search for products",
    "Show my recent orders",
  ]}
/>

Custom Tool Renderers

Render tool results as custom UI instead of JSON:

// Define a custom renderer
function WeatherCard({ data }) {
  return (
    <div className="p-4 rounded-lg bg-blue-50">
      <h3>{data.city}</h3>
      <p className="text-3xl">{data.temperature}°</p>
      <p>{data.conditions}</p>
    </div>
  );
}

// Use it
<CopilotChat
  toolRenderers={{
    get_weather: WeatherCard,
  }}
/>

Tool renderers receive the tool result data as props. Return any React component.


Compound Components

For full layout control, use the compound component pattern:

Basic Structure

import { CopilotChat } from '@yourgpt/copilot-sdk/ui';

<CopilotChat.Root className="h-[600px]">
  {/* Custom home screen */}
  <CopilotChat.HomeView className="gap-6 p-6">
    <h1>Welcome!</h1>
    <CopilotChat.Input placeholder="Ask anything..." />
    <CopilotChat.Suggestions items={["Help", "Pricing"]} />
  </CopilotChat.HomeView>

  {/* Chat view uses default UI */}
  <CopilotChat.ChatView />
</CopilotChat.Root>

Available Components

ComponentDescription
CopilotChat.RootRoot container (alias for CopilotChat)
CopilotChat.HomeViewShows when no messages (home screen)
CopilotChat.ChatViewShows when there are messages
CopilotChat.HeaderHeader slot (view-specific when nested)
CopilotChat.FooterFooter slot
CopilotChat.InputAuto-connected input
CopilotChat.SuggestionsSuggestion buttons
CopilotChat.BackButtonStarts new chat (requires persistence)
CopilotChat.ThreadPickerThread switcher (requires persistence)

View-Specific Headers

Place Header inside ChatView to show it only in chat view:

<CopilotChat.Root persistence={true}>
  {/* Home - no header */}
  <CopilotChat.HomeView>
    <h1>Welcome!</h1>
    <CopilotChat.Input />
  </CopilotChat.HomeView>

  {/* Chat - header with navigation */}
  <CopilotChat.ChatView>
    <CopilotChat.Header className="flex items-center justify-between p-3 border-b">
      <CopilotChat.BackButton />
      <span>Conversation</span>
      <CopilotChat.ThreadPicker />
    </CopilotChat.Header>
    {/* Default messages + input render automatically */}
  </CopilotChat.ChatView>
</CopilotChat.Root>

Custom BackButton

<CopilotChat.BackButton>
  ← Back to Home
</CopilotChat.BackButton>

Context Hook

Access chat context in custom components:

import { useCopilotChatContext } from '@yourgpt/copilot-sdk/ui';

function CustomComponent() {
  const { view, send, isLoading } = useCopilotChatContext();
  return <button onClick={() => send("Hello!")}>Say Hi</button>;
}

Build Your Own Chat

Use hooks for full control:

import { useCopilot } from '@yourgpt/copilot-sdk/react';

function CustomChat() {
  const {
    messages,
    isLoading,
    sendMessage,
    toolExecutions,
  } = useCopilot();

  return (
    <div>
      {messages.map(msg => (
        <div key={msg.id}>
          <strong>{msg.role}:</strong> {msg.content}
        </div>
      ))}

      <input
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            sendMessage(e.currentTarget.value);
            e.currentTarget.value = '';
          }
        }}
        placeholder="Type a message..."
      />
    </div>
  );
}

Styling

The chat component uses Tailwind CSS. Override styles with className:

<CopilotChat
  className="
    h-full
    rounded-xl
    border-2
    border-primary
    bg-background
  "
/>

Next Steps

On this page