---
title: Chat & Messaging
description: The component suite for chat threads, comment sections and AI conversations — messages, delivery status, typing indicators and streaming turns.
visibility: guest
draft: false
---

# Chat & Messaging

Everything you need to build a **chat thread, a comment section, or an AI
assistant conversation** — the human bubble, the assistant turn, the scroll
container that follows new output, the typing indicator, the in-thread markers,
and the file attachments that ride along.

Every piece is token-driven, keyboard-operable, and screen-reader-correct out of
the box — including the parts most chat UIs get wrong (streaming announcements
that don't re-read the whole answer, typing indicators that don't flood a screen
reader, delivery status that is never conveyed by color alone).

:::preview{title="The suite in one thread"}
<div style="width: 24rem; max-width: 100%; margin-inline: auto;">
    <x-wirekit::conversation max-height="22rem" label="Support thread">
        <x-wirekit::stack gap="md">
            <x-wirekit::chat-marker variant="separator">Today</x-wirekit::chat-marker>
            <x-wirekit::message :author="['name' => 'Ada']" timestamp="2026-07-17 09:14">Morning — is the export API rate-limited?</x-wirekit::message>
            <x-wirekit::message :author="['name' => 'You']" side="right" timestamp="2026-07-17 09:15" status="read">Yes, 60 requests a minute per token.</x-wirekit::message>
            <x-wirekit::assistant-message model="atlas-2">
                The export API allows 60 requests per minute per token. A 429 always includes a `Retry-After` header, in seconds.
            </x-wirekit::assistant-message>
        </x-wirekit::stack>
        <x-slot:footer>
            <x-wirekit::message-typing author="Ada" />
        </x-slot:footer>
    </x-wirekit::conversation>
</div>
:::

:::source{language="blade"}
<x-wirekit::conversation max-height="22rem" label="Support thread">
    <x-wirekit::stack gap="md">
        <x-wirekit::chat-marker variant="separator">Today</x-wirekit::chat-marker>
        <x-wirekit::message :author="['name' => 'Ada']" timestamp="2026-07-17 09:14">Morning — is the export API rate-limited?</x-wirekit::message>
        <x-wirekit::message :author="['name' => 'You']" side="right" timestamp="2026-07-17 09:15" status="read">Yes, 60 requests a minute per token.</x-wirekit::message>
        <x-wirekit::assistant-message model="atlas-2">
            The export API allows 60 requests per minute per token. A 429 always includes a `Retry-After` header, in seconds.
        </x-wirekit::assistant-message>
    </x-wirekit::stack>
    <x-slot:footer>
        <x-wirekit::message-typing author="Ada" />
    </x-slot:footer>
</x-wirekit::conversation>
:::

## The components

| Component | What it is |
| --- | --- |
| [Message](/components/message) | The human chat bubble — author, timestamp, side, delivery status (single check = sent, double = delivered, accent double = read), reactions, and attachments. |
| [Conversation](/components/conversation) | The scroll container that holds the thread — sticks to the bottom as output streams, offers a jump-to-latest with an unread count, and preserves the scroll anchor when older history loads. |
| [Assistant Message](/components/assistant-message) | An AI turn — roles, a streaming body, a model chip, a collapsible reasoning disclosure, and announcements a screen-reader user can actually follow. |
| [Message Typing](/components/message-typing) | The three-dot "someone is composing" indicator, indented under the typist's name so the reader sees who is typing. |
| [Chat Marker](/components/chat-marker) | The rows in a thread that are NOT messages — streaming/tool status, system notes, and labeled date breaks. |
| [Attachment](/components/attachment) | A file attachment card — name, size, type, thumbnail, and upload lifecycle — that rides inside a message or stands alone. |
| [Reaction](/components/reaction) | The emoji reaction pill with a count and an active state, for the reactions slot on a message. |

## Where to start

- Building a **human chat or comment thread**? Start with
  [Conversation](/components/conversation) as the container and
  [Message](/components/message) for each bubble.
- Building an **AI assistant UI**? Use [Conversation](/components/conversation)
  plus [Assistant Message](/components/assistant-message), and stream into it —
  the streaming and announcement model is documented on the Assistant Message
  page.
- Need a **live "is typing / is thinking" affordance**? Pin
  [Message Typing](/components/message-typing) (human) or a
  [Chat Marker](/components/chat-marker) `status` row (assistant) to the
  conversation footer.

## Keyboard Interaction

This overview page has no interactive elements of its own. Each component
documents its own keyboard contract on its page — the ones with a keyboard model
are [Conversation](/components/conversation) (the scroll region is a focusable
`role="log"`, reachable and scrollable by keyboard) and
[Reaction](/components/reaction) (an operable toggle). The rest —
[Message](/components/message), [Assistant Message](/components/assistant-message),
[Message Typing](/components/message-typing), and
[Chat Marker](/components/chat-marker) — are presentational; any interactivity
comes from the controls you place in their slots (buttons, menus), which carry
their own keyboard behavior.
