# Empty & first-run state

Show a greeting and starter suggestion chips when the thread has no messages, so new users have somewhere to begin.

A new user lands on a blank thread — give them somewhere to start. Compose a `<kai-empty>` block (icon, headline, subtext) with `<kai-suggestions>` chips **inside** it, so the greeting and the starter prompts read as one piece. Click a chip below to start the conversation.

## Compose the empty block

`<kai-empty>` is a slotted block: an icon in `slot="media"`, the `empty-title` and `description` attributes, and a **default slot** for actions. Drop `<kai-suggestions>` into that default slot and the chips render as part of the first-run composition — not as a separate bar.

When a chip is clicked, `<kai-suggestions>` fires `kai-select` with the chosen value. Swap the empty block for `<kai-chat>` and stream the reply.

```html
<div id="shell" style="height:100%">
  <kai-empty
    id="greeting"
    empty-title="Hi, I'm your assistant"
    description="Ask me anything — or pick a starter below to begin."
  >
    <!-- slot="media" accepts any icon or image -->
    <svg slot="media" width="24" height="24" viewBox="0 0 24 24" fill="none"
         stroke="currentColor" stroke-width="1.75"><path d="M9.5 3 11 8l5 1.5-5 1.5L9.5 16 8 11 3 9.5 8 8z"/></svg>

    <!-- default slot: suggestions live INSIDE the empty block -->
    <kai-suggestions id="starters"></kai-suggestions>
  </kai-empty>
</div>

<script type="module">

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

  const shell = document.getElementById('shell');
  const starters = document.getElementById('starters');
  starters.suggestions = [
    'How do I add AI/UI to a React app?',
    'Theme the components to match my brand',
    'Stream tokens from my own backend',
  ];

  starters.addEventListener('kai-select', (e) => {
    const prompt = e.detail.value;
    // replace the empty block with a live chat, then stream the reply
    shell.innerHTML = '<kai-chat id="chat" style="height:100%"></kai-chat>';
    const chat = document.getElementById('chat');
    chat.messages = [{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text: prompt }] }];
    // …append an assistant message and patch its parts as tokens arrive
  });
</script>
```

> **note:** 
`<kai-empty>`'s default slot is unstyled light DOM, so anything you place there — suggestion chips, a "New chat" button, a sign-in CTA — keeps your page's own styling.

## The simple path: `<kai-chat>`'s built-in suggestions

If you don't need a custom greeting, `<kai-chat>` renders starter suggestions on its own when the thread is empty. Set the `suggestions` property and the chips appear inside the chat's own empty state — no extra components.

Pass an empty `messages` array and a `suggestions` property. `<kai-chat>` hides the suggestions as soon as the first message arrives.

```html
<kai-chat id="chat" chat-title="Assistant" placeholder="Ask me anything…"></kai-chat>

<script type="module">

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

  const chat = document.getElementById('chat');
  chat.messages = [];
  chat.suggestions = [
    'Summarize what you can help me with',
    "What's the best way to get started?",
    'Show me an example',
  ];

  chat.addEventListener('kai-submit', async (e) => {
    const prompt = e.detail.value;
    const aId = crypto.randomUUID();
    chat.messages = [
      ...chat.messages,
      { id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text: prompt }] },
      { id: aId, role: 'assistant', parts: [] },
    ];
    chat.loading = true;
    // stream tokens into the assistant message's `parts`…
    chat.loading = false;
  });
</script>
```

### `submit` vs `fill`

The `suggestionMode` property controls what happens when a user clicks a chip.

| Mode | Behaviour | When to use |
|------|-----------|-------------|
| `'submit'` (default) | Sends the prompt immediately, as if the user typed and hit Enter. | Works well when suggestions are complete questions that need no editing. |
| `'fill'` | Copies the text into the input so the user can edit before sending. | Better for partial prompts or templates (e.g. "Translate this to ___"). |

```js
// submit mode (default) — one-click send
chat.suggestionMode = 'submit';

// fill mode — prefills the input, user edits then sends
chat.suggestionMode = 'fill';
// listen for fill events (kai-submit still fires when they send)
chat.addEventListener('kai-suggestion-click', (e) => {
  console.log('prefilled:', e.detail.value);
});
```

> **tip:** 
Use `'fill'` for guided forms or multi-step prompts where the chip is a starting point, not a finished question.

## Next steps

- **[`kai-chat` reference](/components/chat/)** — full prop and event list, including `suggestions`, `suggestionMode`, `placeholder`, and `chatTitle`.
- **[`kai-empty` reference](/components/empty/)** — props and slots for the empty-state block.
- **[`kai-suggestions` reference](/components/suggestions/)** — standalone suggestion chips for custom layouts outside `<kai-chat>`.
- **[Drop-in chat](/examples/drop-in-chat/)** — the streaming loop that runs once a suggestion is submitted.
