Chat
Usage
The chat display is a set of pieces that stack into a transcript: a scrolling layout, a message log, rows for each sender, bubbles, tool calls, a reasoning disclosure, a typing line, and an unread rule. Message bodies are slots. This suite does not render Markdown; pass plain text, or bring your own renderer.
ChatLayout is a column. The transcript grows, and the composer stays pinned to the bottom over a frosted scrim. By default the layout itself scrolls. Pass scrollRef when an ancestor should scroll instead, and the dock switches from sticky to fixed.
While the reader is at the bottom, new text keeps the view pinned there. Scrolling up lets go immediately and reveals the scroll-to-bottom button. If messages arrive while the view is unlocked, the button label changes to the localized “New messages” string, a live region announces it, and ChatUnreadDivider can mark the boundary. ChatLayout wires this through useChatStreamScroll and useChatNewMessages. Set showScrollButton to false to hide the built-in button, or replace it with the scrollButton slot.
The field is ChatComposer, placed in the layout's composer slot. The shell owns the draft, send, and stop. The default editor accepts chips, sends on Enter, and inserts a newline on Shift+Enter. The attachment drawer, header, and footer are slots. Dictation uses the browser's speech recognition, and the microphone stays hidden when that API is missing. The landing page and the transcript with a document panel are in Patterns.
<script setup lang="ts">
import { ChatComposer, ChatLayout, ChatMessage, ChatMessageBubble, ChatMessageList } from '@astryx-vue/core/Chat'
function onSubmit(value: string) {
console.log(value)
}
</script>
<template>
<ChatLayout>
<ChatMessageList>
<ChatMessage sender="user">
<ChatMessageBubble>
Check the release notes for me.
</ChatMessageBubble>
</ChatMessage>
<ChatMessage sender="assistant">
<ChatMessageBubble name="Assistant">
The notes are in the docs.
</ChatMessageBubble>
</ChatMessage>
</ChatMessageList>
<template #composer>
<ChatComposer placeholder="Type a message…" @submit="onSubmit" />
</template>
</ChatLayout>
</template>ChatMessageList is a role="log". Pass isStreaming while an assistant reply is still growing, so a screen reader waits and announces the finished message once. scrollToTopAction runs when the top sentinel enters the scroll parent, and a spinner stays up until the promise settles.
ChatMessage is an article. sender is user, assistant, or system. A system row is centered and ignores the avatar, name, and metadata slots. Put the visible name on ChatMessageBubble when the body starts with a bubble, so the name lines up with the bubble padding.
ChatToolCalls takes the tool list an assistant turn already produced. One call is a single row. Several calls collapse behind a header; label replaces the localized count while the group is open. A call with detail, or the detail slot, can expand on its own. v-model:is-expanded controls the group.
ChatReasoning is the same kind of disclosure for a thinking trace. It starts collapsed. A plain-text default slot is reused as the one-line preview. isStreaming shimmers the label and hides both the preview and duration.
ChatTypingIndicator draws three dots. Pass names and it writes a sentence for one person, two people, or a named person plus a count. The root is role="status", and that region is the only announcement. ChatUnreadDivider marks the first unread message, and new rows go below it.
The examples start with the composer beside the transcript, then follow layout, scroll button, message, bubble, list, metadata, system message, and tool calls.
Anatomy
| Element | Description |
|---|---|
| Message area | Scrollable region for messages. Renders the default slot (typically ChatMessageList) in a flex column that pushes content to the bottom when the list is short. |
| Frosted glass dock | Sticky or fixed container at the bottom with a backdrop-blur layer. Houses the scroll button and composer. |
| Scroll-to-bottom button | Appears when the user scrolls up or new messages arrive. Defaults to ChatLayoutScrollButton. Set showScrollButton to false to hide it, or replace it with the scrollButton slot. |
| Composer | The input area for sending messages, typically ChatComposer. Docked at the bottom inside the frosted glass layer. |
| Empty state | Centered placeholder shown when no messages exist. Use EmptyState for a consistent look. |
| Avatar | A sender avatar rendered beside the message. Typically Avatar with size="md". Hidden for system messages. |
| Name | Sender name above the message body. Place on the bubble when using bubbles, or on the message wrapper for raw content. |
| Content | The message body: one or more ChatMessageBubble elements, or any free-form slot content like images or tool calls. Wrap non-bubble content in a ghost bubble to align it with the bubble text column. |
| Metadata | Timestamp, delivery status, and footer actions below the message. Place on the last bubble or on the message wrapper. |
Best practices
| Guidance | Practices |
|---|---|
| Do | Keep the transcript in the message list and the composer in the bottom slot, so the frosted dock and the scroll button stay aligned. |
| Do | Set isStreaming for the whole time an assistant body is growing, and clear it when the message is complete. |
| Do | Use ChatUnreadDivider at the first message the reader has not seen. The scroll button’s “New messages” label is the announcement; the divider is the visible mark. |
| Do | Put plain text, citations, or your own renderer in the bubble slot. The bubble only supplies the surface. |
| Don't | Render a second scroll parent inside the layout. One element should own the transcript scroll, either the layout or the element passed as scrollRef. |
| Don't | Announce every streamed token yourself. The typing indicator speaks once through its own role="status", and the new-message label speaks through the layout live region. |
Examples
ChatLayout — Panel View
A narrow column. Press Enter and the draft is appended to the transcript. A tight container uses compact density, which fits a side panel or a drawer.
ChatComposer — Shell
A field with an attachment drawer, a header button, and dictation. With no text the send button is muted and cannot be clicked; it turns into the solid button once there is something to send. Attachments alone do not enable it. The drawer handle collapses the attachments. The microphone starts listening in browsers that support speech recognition.
ChatComposer — States
The top field is disabled while a reply is in progress, and Stop stays clickable. The middle one is compact and flat, with a warning. The bottom one puts an error above the field.
ChatComposerInput — Mentions
Type @ at the start of a word and keep going through spaces, as in Ada Lov, and the list narrows to Ada Lovelace. Arrow keys move the highlight, and Enter inserts that row rather than the first person in the list. A phrase with no match hides the list and leaves the typed text alone. Type / for a one-word command; a space closes that list. A person becomes a chip. A command is inserted as text.
ChatTokenizedText — Chips in a bubble
The same chip definitions render inside a sent bubble.
ChatLayoutScrollButton — Labels
Labels expand the button to give context
Scroll button with different labels for context-specific notifications like new messages, unread replies, or a generic scroll prompt.
ChatMessage — Avatar & Name
Messages with avatars and sender names. Place the name on the bubble when using bubbles, or on the message wrapper for raw content.
ChatMessage — Ghost
Ghost variant for messages without visible bubble boundaries. Keeps padding for alignment but renders a transparent background, useful for AI-style responses.
ChatMessage — Multi-Bubble
Grouped bubbles using the group prop for corner radius reduction. Use first, middle, and last to visually connect related bubbles from the same sender.
ChatMessageBubble — Custom Content
Custom in-message content aligned to the bubble text column. A ghost bubble spans the message column, and the timestamp rides the bubble metadata slot.
ChatMessageBubble — Density
Compact
Balanced
Spacious
Compact, balanced, and spacious density modes side by side. Density controls bubble padding, corner radius, and spacing between grouped bubbles.
ChatMessageBubble — Grouping
Multi-bubble messages using first, middle, and last group positions. Grouped bubbles tighten corner radius on the sender side.
ChatMessageBubble — Metadata
Bubbles with name and metadata slots aligned to bubble padding. Put name on the first bubble and metadata on the last bubble in a message.
ChatMessageBubble — Variants
Filled and ghost bubble variants for both user and assistant senders. Use filled for standard messages and ghost when content needs alignment without a visual boundary.
ChatMessageList — Density
Compact
Balanced
Spacious
Side-by-side comparison of compact, balanced, and spacious densities. Use compact in sidebars, balanced for most full-page chat, and spacious for long-form reading.
ChatMessageList — Full Featured
A transcript with a date divider, file names, a code sample, ghost bubbles, and metadata.
ChatMessageMetadata — Footer Actions
Assistant message with footer actions: copy, retry, thumbs up/down, and model label.
ChatMessageMetadata — Status
All 5 delivery statuses (sending, sent, delivered, read, and error), each with a timestamp.
ChatMessageMetadata — Timestamps
Timestamp-only metadata on user and assistant messages. Supports an absolute time and a relative label.
ChatSystemMessage — Icon
System messages with a leading icon that reinforces the message type.
ChatSystemMessage — Status Updates
Status messages in a conversation flow: membership changes, a topic change, dates, and a resolution notice.
ChatSystemMessage — Variants
Default
Divider
Default and divider variants side by side. Use default for inline status updates and divider for date separators.
ChatToolCalls — Expandable
Tool calls with expandable result details. Click a row to reveal its result.
ChatToolCalls — Simple
A single inline tool call above a collapsible multi-call group with diff stats.
ChatToolCalls — Statuses
All four status states (pending, running, complete, and error) shown together in a single group.