AIChatPanel

A chat panel for AI-assisted coding workflows. It renders user and assistant messages with markdown and code block support, file @ mentions with autocomplete, and a streaming indicator.

Import

import { AIChatPanel } from "@run0/jiki-ui";
import type { ChatMessage, InspectedElement } from "@run0/jiki-ui";

Props

PropTypeDefaultDescription
messagesChatMessage[]—Message history to display
onSendMessage(content: string) => void—Called when the user sends a message
isStreamingboolean—Show streaming indicator on last message
accentColorAccentColor"blue"Theme color
titlestring"Chat"Panel header title
modelLabelstring—Model badge label (e.g. "GPT-4o")
onLoadMore() => void—Callback to load earlier messages
hasMoreMessagesboolean—Whether older messages are available
filePathsstring[]—File paths for @ mention autocomplete
inspectedElementInspectedElement | null—Inspected element context badge
onClearInspectedElement() => void—Clear the inspected element context

ChatMessage

interface ChatMessage {
  id: string;
  role: "user" | "assistant";
  content: string;        // Supports markdown with ```code blocks
  timestamp: number;
  isStreaming?: boolean;   // Show pulse dot during streaming
}

Features

  • User and assistant message bubbles with distinct styling
  • Markdown rendering with collapsible code blocks
  • Long messages are collapsible with a “Show more” toggle
  • @ mention autocomplete filtered against filePaths
  • File mention rendering with a file icon
  • Streaming pulse dot indicator
  • Auto-scroll to bottom (respects manual scroll position)
  • Inspected element context badge from BrowserWindow
  • Auto-resizing textarea (max 200px)
  • IntersectionObserver for lazy-loading older messages
  • Enter to send, Shift+Enter for newline

Usage

const [messages, setMessages] = useState<ChatMessage[]>([]);
const [streaming, setStreaming] = useState(false);

<AIChatPanel
  messages={messages}
  onSendMessage={async (content) => {
    setMessages((prev) => [
      ...prev,
      { id: crypto.randomUUID(), role: "user", content, timestamp: Date.now() },
    ]);
    setStreaming(true);
    const reply = await askModel(content);
    setMessages((prev) => [
      ...prev,
      { id: crypto.randomUUID(), role: "assistant", content: reply, timestamp: Date.now() },
    ]);
    setStreaming(false);
  }}
  isStreaming={streaming}
  accentColor="violet"
  modelLabel="Claude"
  filePaths={["src/index.ts", "src/App.tsx", "package.json"]}
/>

Demo

Chat
Demo
Hi! Ask me anything. Try typing `@` to mention a file.

Enter to send · Shift+Enter for newline · @ to reference files