Skip to content

Conversation

A whole chat thread, put together from the other conversation parts. Pass messages and the status of the reply, and it groups messages by sender, separates days, follows the latest message, shows tools and attachments, opens images in a lightbox, and offers copy, regenerate, edit and feedback wherever you pass a handler. A finished reply is read to screen readers once, and nothing is read while it streams; what is read is the message text, so keep it plain. It fetches nothing: what the user does is reported through the callbacks.

Roles

A user message is a bubble on the right, an assistant message sits on the left with its avatar and name, and a system message is a quiet line in the middle. MessageBubble takes the content as children and leaves the time and the actions to snippets.

The assistant joined the conversation
Does the starter kit work with any lamp?
MG

Madam Glam

It needs a UV or LED lamp that cures at 365 to 405 nm. Most lamps sold for gel polish do.

Grouped and single

Messages from the same sender in a row share one avatar and name, and a time shows once under the last of them. A sender who comes back after someone else starts a new group.

MG

Madam Glam

Hi! I can help you pick a kit.

What are you painting, hands or feet?

Hands.

MG

Madam Glam

Then the starter kit is the right size.

Long text and code

Text keeps its line breaks, and long lines wrap inside the message. Pass a content snippet to render a message your own way, such as Markdown.

MG

Madam Glam

Cure each thin layer for 60 seconds, then wipe with isopropyl alcohol.

If the polish bubbles, the layer was too thick. Apply it thinner and cure again.

You can check the lamp with this snippet from the kit guide:

const wavelength = 365;
const seconds = wavelength > 380 ? 90 : 60;

Attachments

MessageAttachments lays out a message's files: an image with a url as a thumbnail, any other file as a chip with its name and size that opens in a new tab. Its images open in one Lightbox that pages through every image of the message. Conversation renders one per message; reach for it on its own when you compose bubbles by hand.

This is what I got. Any idea why it lifted?

receipt.pdf 180 KB
MG

Madam Glam

The edges lifted because the polish touched the skin. Leave a hair of space.

Queued messages

A message sent while a reply is still coming shows as queued, under the bubble, until it goes out.

Does it ship to Canada?

MG

Madam Glam

Yes, in two to four business days.

And how much is shipping?

Queued

Streaming

status drives the thread. submitted shows the typing indicator, streaming lets the reply grow in place and holds back its actions, and ready brings them back. A screen reader hears nothing while the reply streams, then the finished reply once as plain text.

MG

Madam Glam

Ask me anything about your order.

Error and retry

An error shows after the last message with a retry button. The thread keeps everything that was said, so the shopper can see what failed.

Does it ship to Canada?

Tool states

A tool the assistant ran shows its state and how long it took, and expands to the arguments and the result or the error. Show a friendly label: the internal tool name appears only when there is no label.

Arguments

{
  "query": "gel starter kit",
  "limit": 3
}

Arguments

{
  "query": "gel starter kit",
  "limit": 3
}

Result

{
  "found": 3,
  "top": "At-Home Gel Starter Kit"
}

The inventory service did not answer in time.

Several tools in one reply

A reply can carry any number of tools. They sit above its text, in the order they ran.

Find me a starter kit and check it ships to Canada.

MG

Madam Glam

Arguments

{
  "query": "gel starter kit",
  "limit": 3
}

Result

{
  "found": 3,
  "top": "At-Home Gel Starter Kit"
}

Result

{
  "country": "CA",
  "days": "2 to 4"
}

The At-Home Gel Starter Kit is in stock and ships to Canada.

Several days

A separator marks each new day, labelled Today, Yesterday or the date in the reader's locale. Runs of messages never carry across midnight.

Is the kit back in stock?

MG

Madam Glam

Not yet, it should be back next week.

Can you tell me when it is?

MG

Madam Glam

It is back now. I can add it to your cart.

Yes please.

Message actions

Copy is always there. Regenerate, edit and feedback appear where you pass their handler, and items adds a menu for the rest. The actions are one tab stop, and the arrow keys move between them. In the thread they show when the pointer or keyboard focus is on the message.

Feedback: none. Last action: none.

Empty and loading

With no messages the thread shows a line of text, or whatever you pass as empty. While loading, it shows placeholders shaped like messages, so nothing jumps when they arrive.

Ask me anything

About sizes, shipping or your order.

Jump to latest

The thread follows new messages while you are at the bottom. Scroll up to read, then add a message: it stays where you are and offers a button to go back.

Question number 1?

MG

Madam Glam

Here is a bit more detail about that.

Question number 2?

MG

Madam Glam

Here is a bit more detail about that.

Question number 3?

MG

Madam Glam

Here is a bit more detail about that.

Question number 4?

MG

Madam Glam

Here is a bit more detail about that.

Question number 5?

MG

Madam Glam

Here is a bit more detail about that.

Question number 6?

MG

Madam Glam

Here is a bit more detail about that.

Question number 7?

MG

Madam Glam

Here is a bit more detail about that.

Mobile width

The thread holds its shape at 375 px: bubbles wrap, and the tool rows truncate instead of overflowing.

MG

Madam Glam

Hi! I can help you pick a kit.

What are you painting, hands or feet?

Hands.

MG

Madam Glam

Then the starter kit is the right size.

Arguments

{
  "query": "gel starter kit",
  "limit": 3
}

Result

{
  "found": 3,
  "top": "At-Home Gel Starter Kit"
}

Cure each thin layer for 60 seconds, then wipe with isopropyl alcohol. Do not skip the wipe: it removes the sticky layer that makes the next coat lift.

API

Conversation

A whole chat thread, put together from the other conversation parts. Pass messages and the status of the reply, and it groups messages by sender, separates days, follows the latest message, shows tools and attachments, opens images in a lightbox, and offers copy, regenerate, edit and feedback wherever you pass a handler. A finished reply is read to screen readers once, and nothing is read while it streams; what is read is the message text, so keep it plain. It fetches nothing: what the user does is reported through the callbacks.

Prop Type Default Description
messages required ConversationMessage[]

The thread, oldest first.

status 'ready'|'submitted'|'streaming'|'error' 'ready'

Where the reply is. submitted shows the typing indicator; streaming hides the actions of the reply still being written.

loading boolean false

Shows placeholders in place of the messages.

error string

What went wrong. Shown after the last message with a retry button.

onRetry () => void

Called when retry is pressed.

assistant ConversationPerson { name: 'Assistant' }

Who the assistant is.

onRegenerate (message: ConversationMessage) => void

Shows Regenerate on the latest assistant reply.

onEdit (message: ConversationMessage) => void

Shows Edit on user messages.

onFeedback (message: ConversationMessage, feedback: 'up'|'down'|null) => void

Shows thumbs up and down on assistant replies.

menuItems import('./conversation-message-actions.svelte').MessageActionItem[] []

Extra actions for every message, in a menu.

empty import('svelte').Snippet

What to show when there are no messages.

content import('svelte').Snippet<[ConversationMessage]>

Renders a message's text, for example as Markdown. Defaults to the plain text.

class string

Additional Tailwind classes merged onto the viewport, which fills the space left in a flex column: give that column a height.

ConversationHeader

The bar at the top of a conversation: a title with an optional line under it, such as the model in use or the assistant's status, and room for your own controls on either side.

Prop Type Default Description
title required string

Name of the conversation or of who it is with.

description string

A line under the title, such as a status or the model in use.

leading import('svelte').Snippet

Controls before the title, such as an avatar or a back button.

actions import('svelte').Snippet

Controls after the title, such as a new chat button or a menu.

class string

Additional Tailwind classes merged onto the header.

ConversationViewport

The scrolling area of a conversation. It follows new messages to the bottom, but only while the reader is already there: once they scroll up to read something, it stays put and offers a "Jump to latest" button instead.

Prop Type Default Description
children required import('svelte').Snippet

The messages.

class string

Additional Tailwind classes merged onto the viewport, which fills the space left in a flex column: give that column a height, or there is nothing to scroll.

MessageBubble

One message. A user message is a bubble on the right, an assistant message sits on the left with its avatar and name, and a system message is a quiet centred line. In a run of messages from the same sender, set grouped on every one after the first to drop the repeated avatar and name. queued marks a message that has not been sent yet. Actions stay hidden until the pointer or keyboard focus is on the message, and are always visible on touch screens.

Prop Type Default Description
children required import('svelte').Snippet

The message content.

role 'user'|'assistant'|'system' 'assistant'

Who said it.

name string

The sender's name, shown above an assistant message and used for the avatar's initials.

avatar string

Image URL for the sender's avatar.

grouped boolean false

Continues a run from the same sender, so the avatar and name are left out.

queued boolean false

The message is waiting to be sent.

meta import('svelte').Snippet

Small print under the message, such as a MessageTimestamp.

actions import('svelte').Snippet

Controls for the message, such as MessageActions.

class string

Additional Tailwind classes merged onto the message.

MessageTimestamp

The time a message was sent, in the user's locale. Hovering or focusing it shows the full date and time, and a screen reader reads the full date and time instead of the short one.

Prop Type Default Description
date required Date|string|number

When the message was sent.

class string

Additional Tailwind classes merged onto the time.

MessageActions

The actions for one message, as a toolbar that is a single tab stop with the arrow keys moving between them. Copy is always there. The others appear when you pass their handler: regenerate and feedback on an assistant message, edit on a user message. items adds a menu for anything else.

Prop Type Default Description
role required 'user'|'assistant'

Whose message the actions belong to.

text required string

What Copy puts on the clipboard.

feedback 'up'|'down'|null null

The feedback already given, if any.

onRegenerate () => void

Shows Regenerate on an assistant message and is called when it is pressed.

onEdit () => void

Shows Edit on a user message and is called when it is pressed.

onFeedback (feedback: 'up'|'down'|null) => void

Shows thumbs up and down on an assistant message; called with the new feedback, or null when it is withdrawn.

items MessageActionItem[] []

Extra actions, shown in a menu after the others.

class string

Additional Tailwind classes merged onto the actions.

MessageAttachment

A file attached to a message. An image with a url shows as a thumbnail, and any other file as a chip with its name and size. Pass onview to open the image in place, as MessageAttachments does with its Lightbox; otherwise either one opens the file in a new tab when it has a url.

Prop Type Default Description
attachment required ConversationAttachment

The file to show.

onview () => void

Called when the thumbnail of an image is pressed, in place of opening it in a new tab.

class string

Additional Tailwind classes merged onto the attachment.

MessageAttachments

The files attached to one message, in a row that wraps. Its images open in a single Lightbox that pages through every image of the message; other files open in a new tab.

Prop Type Default Description
attachments required import('./conversation-message-attachment.svelte').ConversationAttachment[]

The message's files, in order.

class string

Additional Tailwind classes merged onto the row.

DateSeparator

A divider between messages from different days, labelled "Today", "Yesterday" or the date in the user's locale.

Prop Type Default Description
date required Date|string|number

A moment on the day the separator introduces.

class string

Additional Tailwind classes merged onto the separator.

ToolExecution

One tool the assistant ran, shown as a row with its state and how long it took. Expanding it reveals the arguments and the result or the error. Show a friendly label to shoppers; name is the internal tool name and appears only when there is no label.

Prop Type Default Description
name required string

Internal tool name.

label string

What to show instead of the internal name.

state 'pending'|'running'|'success'|'error' 'pending'

Where the call is.

duration number

How long it took, in milliseconds.

input *

The arguments, shown when expanded.

output *

The result, shown when expanded.

error string

What went wrong, shown when expanded.

open bindable boolean false

Whether the details are showing. Two-way bindable via bind:open.

class string

Additional Tailwind classes merged onto the row.

TypingIndicator

Three pulsing dots that show a reply is being prepared. For a screen reader it is a status that reads "Assistant is typing".

Prop Type Default Description
class string

Additional Tailwind classes merged onto the indicator.

ConversationMessage

Prop Type Default Description
id required string

Stable key for the message.

role required 'user'|'assistant'|'system'

Who said it.

text required string

What was said.

createdAt required Date|string|number

When it was sent.

status 'queued'

queued while the message waits to be sent.

attachments import('./conversation-message-attachment.svelte').ConversationAttachment[]

Files sent with the message.

tools import('./conversation-tool-execution.svelte').ConversationTool[]

Tools the assistant ran for this reply.

feedback 'up'|'down'

The feedback already given on an assistant reply.

ConversationPerson

Prop Type Default Description
name required string

Display name.

avatar string

Image URL.

MessageActionItem

Prop Type Default Description
label required string

Text of the menu entry.

onSelect () => void

Called when the entry is chosen.

disabled boolean

Disables the entry.

separator boolean

Draws a divider in place of an entry.

destructive boolean

Styles the entry as a dangerous action.

ConversationAttachment

Prop Type Default Description
id required string

Stable key for the attachment.

name required string

File name.

type required string

MIME type, such as image/png or application/pdf.

size number

Size in bytes.

url string

Where the file can be opened.

ConversationTool

Prop Type Default Description
id required string

Stable key for the tool call.

name required string

Internal tool name.

label string

What to show instead of the internal name.

state required 'pending'|'running'|'success'|'error'

Where the call is.

duration number

How long it took, in milliseconds.

input *

The arguments, shown when expanded.

output *

The result, shown when expanded.

error string

What went wrong, shown when expanded.