# Chat

A full-featured chat UI — thread, prompt composer, and optional header — packaged as a single Shadow DOM web component that drops into any framework.

<p class="kai-tag-sub">kai-chat</p>

A full-featured chat UI — thread, composer, and optional header — packaged as a single Shadow DOM web component for any framework.

## Preview

> **tip:** 
Reach for `<kai-chat>` when you need a **drop-in chat panel in a non-Solid codebase** — React, Vue, a plain HTML page, or an iframe. It isolates all styles in Shadow DOM and bundles its own SolidJS runtime. Give the element an explicit height (e.g. `height: 100vh`) — it fills its block, scroll and all. Add custom header controls through its [header slots](/patterns/custom-chat-header/). Need a built-in **conversation sidebar and history** too? Use [`<kai-workspace>`](/components/workspace/). For fine-grained control in SolidJS, compose `ChatThread`, `Message`, and `PromptInput` directly.

## Usage

Set rich data (arrays, objects) in JavaScript; scalar props work as attributes or properties:

```html
<kai-chat id="chat" style="display:block; height:100vh;"></kai-chat>

<script type="module">

  await customElements.whenDefined('kai-chat');

  const chat = document.getElementById('chat');

  chat.messages = [
    { id: '1', role: 'user', parts: [{ type: 'text', text: 'How do I center a div?' }] },
    { id: '2', role: 'assistant', parts: [{ type: 'text', text: 'Use `display: grid; place-items: center;`' }],
      actions: ['copy', 'like', 'dislike'] },
  ];

  chat.addEventListener('kai-submit', (e) => {
    console.log('user sent:', e.detail.value, 'attachments:', e.detail.attachments);
  });
  chat.addEventListener('kai-message-action', (e) => {
    console.log(e.detail.messageId, e.detail.action);
  });
</script>
```

- **`messages`** — each entry: `id`, `role` (`'user' | 'assistant'`), an ordered `parts` array (`text` rendered as markdown for assistant, plus `reasoning`, `tool`, `card`, `source`, `file`), and optional `actions`, `avatar`, and `feedback`.
- **`loading`** — flip to `true` while awaiting a reply; the input disables and a typing indicator appears.

### Message actions

Add `actions: ['copy', 'like', 'dislike']` to a message and the action row is wired for you. `copy` writes to the clipboard and shows a check; `like` / `dislike` mark the vote, hide the other, and toggle off on a second tap. Each raises a [toast](/components/toast/). See [Message](/components/message/#the-action-row) for the full behavior.

`kai-message-action` reports votes with a `state` field — `'on'` when set, `'off'` when cleared:

```js
chat.addEventListener('kai-message-action', (e) => {
  const { messageId, action, state } = e.detail;
  if ((action === 'like' || action === 'dislike') && state === 'on') {
    saveVote(messageId, action);
  }
});
```

Set `feedback: 'like' | 'dislike'` on a message to re-hydrate a persisted vote; it wins over the element's optimistic state.
- **Model switcher** — set `models` (`{ id, name, provider? }[]`) and `currentModel`; listen for `kai-model-change`.
- **Context meter** — set `context` (`{ usedTokens, maxTokens, … }`) to show a token-usage gauge in the header.

## Examples

### Basic Thread

### Loading State

### Starter Suggestions

`suggestions` — clickable prompts above an empty thread; `suggestion-mode="fill"` populates the input instead of submitting.

### Model Switcher and Header

`models` + `chat-title` activates the header bar with a model-switcher dropdown.

### Context Token Meter

Add `context` to show a live token-usage gauge — yellow near the warning threshold, red near danger.

### Entity Pills

Set `triggers` so `/` inserts a skill pill and `@` opens a sectioned menu of agents and plugins. `kai-submit` carries the structured `doc` + `entities` for your backend to expand.

## Slots

`<kai-chat>` is a frame: keep the built-in thread and project your own chrome into named slots. An `inject` slot adds to a region; a `replace` slot stands in for it (you own that region's data and events). See [Compose your own shell](/patterns/compose-your-own/) for a worked example.

## Styling

Restyle the built-in regions from outside via `::part` — no shadow piercing.

## Props

## Events

## Methods

## Composed from
