Skip to content
kitn AI/UI

Drop-in chat

One element gives you the whole experience: a message thread with markdown, reasoning, and tool calls, a composer, and optional header chrome. You bring the model; <kai-chat> renders the UI. The thread starts empty with a few starter suggestions — click one to begin, and the reply streams in.

Start with an empty thread and a few suggestions. The chips render in the empty state and disappear once the conversation has a message, so they read as conversation starters. Assign both in JavaScript (arrays can’t be HTML attributes), then handle kai-submit: append the user’s turn, add an empty assistant message, and grow its content as tokens arrive.

<kai-chat id="chat" chat-title="Assistant" placeholder="Ask anything…"></kai-chat>
<script type="module">
import '@kitn.ai/ui/elements';
const chat = document.getElementById('chat');
chat.messages = [];
chat.suggestions = [
'What makes kitn-chat different from rolling my own?',
'Show me a streaming example',
];
chat.addEventListener('kai-submit', async (e) => {
const prompt = e.detail.value;
const aId = crypto.randomUUID();
// append the user turn + an empty assistant message
chat.messages = [
...chat.messages,
{ id: crypto.randomUUID(), role: 'user', content: prompt },
{ id: aId, role: 'assistant', content: '' },
];
chat.loading = true;
// stream tokens from your backend into the assistant message
for await (const token of streamFromYourModel(prompt)) {
chat.messages = chat.messages.map((m) =>
m.id === aId ? { ...m, content: m.content + token } : m,
);
}
chat.loading = false;
});
</script>

The key move is reassigning chat.messages to a new array on each token — that’s what drives the re-render.