Conversation

Top-level chat shell that sticks to the latest turn, with empty, scroll, streaming, and download controls.

Conversation is the scroll shell around a chat transcript. It sticks to the latest turn while content grows, shows a jump-to-latest control when the reader scrolls away, and can export the thread as Markdown. Pair it with Message, Bubble, Marker, and Attachment for every AI turn state.

Oliver
How can I help you today?
It's 4:55 PM
ER
Summarize the latest deploy notes.
Delivered
Deploy shipped with the conversation shell, scroll-to-latest, and Markdown export.
❤️
Oliver is typing...

Installation

pnpm dlx cubix@latest add conversation --base radix

Usage

Import
import {
  Conversation,
  ConversationContent,
  ConversationEmptyState,
  ConversationScrollButton,
  ConversationDownload,
} from "@/components/cubix/conversation"
Example
<Conversation>
  <ConversationContent>
    <Message>...</Message>
  </ConversationContent>
  <ConversationDownload messages={messages} />
  <ConversationScrollButton />
</Conversation>

Note: Conversation owns the viewport - stick-to-bottom, empty state, scroll, and download. Message owns each row inside it.

Composition

 
Conversation
├── ConversationContent
   ├── ConversationEmptyState
   ├── Marker…
   ├── MessageGroup…
   └── Message…
├── ConversationDownload
└── ConversationScrollButton

Features

  • Sticks to the bottom as new messages arrive
  • Smooth resize follow while streamed content grows
  • Scroll button when the reader leaves the latest turn
  • Optional Markdown download of the thread
  • Empty state for cold starts
  • Hosts typing, generating, streaming, stopped, failed, attachment, and action rows via Message parts

Empty state

Render ConversationEmptyState when the thread has no messages yet.

Start a conversation

Type a message below to begin chatting.

Scroll button

Scroll up in the preview to reveal ConversationScrollButton.

ER
Can you walk me through the release checklist?
Sure. Start with the changelog, then run the smoke suite.
ER
What about migrations?
Run them before traffic cutover, and keep a rollback script ready.
ER
And monitoring?
Watch error rate, latency p95, and queue depth for the first hour.
ER
Perfect. Anything else?
Post a short status update once the cutover is stable.
ER
Thanks - I'll start with the changelog.
Sounds good. Ping me if anything in the smoke suite fails.
ER
One more thing - who owns the rollback?
Ops owns rollback. Keep the previous image tagged and ready.

Download

Use ConversationDownload to export the thread as Markdown. Pass plain { role, text } messages - no AI SDK types required.

How can I help you today?
ER
Summarize the latest deploy notes.
Deploy shipped with the conversation shell, scroll-to-latest, and Markdown export.

Typing

Show a peer typing indicator with Marker while the shell stays stuck to the bottom.

ER
Summarize the latest deploy notes.
Delivered
Oliver is typing...

Generating

Before the first token arrives, render a spinner status row inside the transcript.

ER
Check the deploy logs for timeouts.
Generating a response...

Streaming

Grow a single assistant bubble as tokens arrive. Offer Stop while streaming, then switch to copy and feedback actions when done.

ER
How does the deploy look so far?

Stopped

When the user stops generation mid-reply, keep the partial text and offer a continue control.

ER
Write a long postmortem for the outage.
At 14:12 UTC the API gateway started returning 502s after the canary rollout...
Generation stopped

Failed turns

Cover both failed user sends and failed model generations with retry actions.

ER
Retry the failed install for me.
Failed to send
I started the retry.

Generation failed

The model timed out after 30s. Try again.

Attachments

Nest Attachment under MessageContent for files sent by the user or returned by the assistant.

ER
Can you add a cover page to this report?
sales-dashboard.pdfPDF · 2.4 MB
Done. Here's the PDF with the image added as the cover page.
sales-dashboard.pdfPDF · 2.6 MB

Response actions

After a completed assistant turn, expose copy, feedback, and regenerate in the message footer.

How can I help you today?
ER
Summarize the latest deploy notes.
Deploy shipped with the conversation shell, scroll-to-latest, and Markdown export.

Message groups

Nest MessageGroup for stacked turns from the same sender. Use a separator marker for day breaks. Empty MessageAvatar keeps earlier bubbles aligned with the final avatar.

I checked the registry addresses.
They look correct. Want me to retry the install?
ER
Yes, please retry it.
Delivered
Retrying now. I'll report back.

Live thread

As whole messages append, the shell follows the latest turn. Scroll away to reveal the jump button.

Start a conversation

Messages will appear here as the thread progresses.

API Reference

Conversation

PropTypeDefaultDescription
classNamestring-Additional classes for the conversation root.
initial"smooth" | "instant" | false"smooth"Scroll behavior when the conversation first mounts.
resize"smooth" | "instant" | false"smooth"Scroll behavior when content size changes.

ConversationContent

PropTypeDefaultDescription
classNamestring-Additional classes for the scrollable content area.

ConversationEmptyState

PropTypeDefaultDescription
titlestring"No messages yet"Empty-state heading.
descriptionstring"Start a conversation to see messages here."Supporting empty-state copy.
iconReact.ReactNode-Optional icon above the empty-state title.
childrenReact.ReactNode-Replace the default empty layout with custom content.

ConversationScrollButton

PropTypeDefaultDescription
classNamestring-Additional classes for the jump-to-latest button. Hidden while at the bottom.

ConversationDownload

PropTypeDefaultDescription
messagesConversationMessage[]-Messages to export as Markdown. Each item needs role and text.
filenamestring"conversation.md"Download filename.
formatMessage(message, index) => string-Optional formatter for each Markdown line.
childrenReact.ReactNode-Optional custom icon or label inside the download button.