Components / AI interface

ChatPanel

Tabbed chat panel with reasoning replies and a composer.

Install

npx shadcn@latest add https://irisui.dev/r/chat-panel.json
import ChatPanel from "@/components/iris/chat-panel/chat-panel";
Registry item chat-panelBrings in foundationRegistry JSON

Preview

ChatPanel

A compact, fixed-height chat panel with context tabs, a user prompt, labelled agent replies and a composer.

When to use

  • Embed a small assistant panel in a side rail or a dashboard tile, where a few labelled reply sections ("Pageviews · capydb.dev for 4s") explain what the agent did.
  • Demonstrate an agent's reply sequence: after a send, the bubble appears and the two replies resolve one after another.
  • Not for a full conversation thread with history — use ChatThread (and its ChatComposer input). Not for a standalone input with @ sources, / commands and a model picker — use PromptBar.

Usage

import ChatPanel from "@/components/iris/chat-panel/chat-panel";

h(ChatPanel, {
  suggestions: ["Websites", "Funnels"],
  labels: { initialPrompt: "Compare capydb.dev traffic to last month", placeholder: "Ask or tag a website with @" },
  messages: [
    { label: "Pageviews", sub: "capydb.dev", time: "4s", body: "Pulled 30 days of pageviews for /pricing and /docs." },
    {
      label: "Comparison",
      sub: "Trend detection",
      time: "2s",
      body: "/pricing is up 12 % with stronger weekday peaks.",
    },
  ],
  onSend: (text) => ask(text),
});

Props

Prop Type Default Description
messages { label: string; sub: string; time: string; body: string }[] 2 analytics replies Scripted agent replies. Only the first two are rendered. label, sub and time form the header line ("label sub for time").
suggestions string[] ["Websites", "Funnels"] Header tabs. The first is selected initially. Tabs are visual only and do not filter the replies.
labels Partial<{ initialPrompt: string; placeholder: string }> Compare capydb.dev traffic to last month / Ask or tag a website with @ initialPrompt fills the first user bubble, and placeholder is the composer placeholder.
onSend (text: string) => void — Fired with the trimmed prompt on Enter or on the send button.
variant string — Accepted for gallery parity. It has no effect.

Notes

  • The panel is 288px tall and at most 380px wide, and the thread scrolls inside it. It opens in the finished state, showing the initial prompt and both replies.
  • Sending replaces the bubble text and replays the same scripted replies. Wire onSend to your own backend and update messages to show real output.
  • The header icon buttons (new, history, more) are decorative and all share aria-label="Action". Give them real labels and handlers if you ship them.
  • The send button is disabled until the field has text. Reads --surface, --field, --line, --line-strong, --ink, --ink-2 and --ink-3.