Manual UI Templates MessageList

MessageList

elements man ui/templates/message-list

A conversation that stays pinned to the newest message unless the reader scrolls up.

Example
import { MessageList, MessageListEmpty, MessageListDownload } from "@elements/ui/message-list"; import { Message, MessageContent, MessageResponse } from "@elements/ui/message"; <MessageList busy={reply.streaming}> <MessageListEmpty e:if={messages.length === 0} /> <Message e:for={m of messages} e:key={(m) => m.id} from={m.role}> <MessageContent><MessageResponse markdown={m.text} /></MessageContent> </Message> <MessageListDownload slot="overlay" messages={messages} /> </MessageList>

Parts

Part What it is
MessageList The scroller. Fills its container's height and follows new content while at the bottom.
.message-list-viewport role=log, focusable so the keyboard can scroll it.
.message-list-content The messages, spaced by --message-list-gap; grouped follow-ups sit closer.
.message-list-scroll Scroll to latest: shown when not at the bottom, floating over the messages.
MessageListEmpty A centered placeholder for an empty conversation.
MessageListDownload Saves the conversation as a Markdown file.
messagesToMarkdown() The Markdown the download writes; takes an optional formatter.

Attributes

MessageList

Attribute Type Default Description
label string "Conversation" The log's accessible name.
stickToBottom boolean true Follow new content while at the bottom.
initial "smooth" | "instant" | "none" | { damping, stiffness, mass } "smooth" How it reaches the newest message on mount.
resize "smooth" | "instant" | { damping, stiffness, mass } "smooth" How it follows growing content: native smooth, instant, or a spring (defaults 0.7, 0.05, 1.25). Reduced motion makes every mode instant.
contentClass string "" Extra classes on the content wrapper.
contentAttrs Record<string, string | number | boolean | undefined> {} Attributes spread on the content wrapper.
threshold number 70 Pixels from the end that still count as at the bottom.
targetScrollTop ((target, { scrollElement, contentElement }) => number) | null null Moves the bottom the list follows, such as the top of the newest reply; clamped to the scroll range.
atBottom boolean (two-way) true False once the reader scrolls up. Set it true to scroll down and follow again.
busy boolean false aria-busy on the log while a reply streams, so it is announced once, finished.
scrollButton boolean true Render the scroll to latest button.
scrollButtonLabel string "Scroll to latest" Its accessible name.
scrollButtonVariant "primary" | "secondary" | "outline" | "ghost" | "link" | "danger" "outline" The scroll button's variant.
scrollButtonClass string "" Appended to the scroll button's class.
scrollButtonAttrs Record<string, string | number | boolean | undefined> {} Attributes spread on the scroll button.
onAtBottomChange (atBottom: boolean) => void () => {} Fires when the reader leaves or reaches the bottom.
class string "" Extra classes on the root.
attrs Record<string, string | number | boolean | undefined> {} Other attributes for the root.

MessageListEmpty

Attribute Type Default Description
title string "No messages yet" Heading.
description string "Start a conversation to see messages here" Text under it.

MessageListDownload

Attribute Type Default Description
messages ChatMessageLike[] (required) { role, text?, content?, parts? }. Messages from common AI chat toolkits, with text in parts, work as they are.
filename string "conversation.md" The saved file's name.
formatMessage (message, index) => string **Role:** text Formats each message.
label string "Download conversation" Accessible name and tooltip.

Slots

Slot Part Content
default MessageList Messages, or a MessageListEmpty.
overlay MessageList Floating controls at the top inline end, such as MessageListDownload.
scroll-icon MessageList Replaces the scroll button's arrow icon.
icon MessageListEmpty An icon above the title.
default MessageListEmpty Extra content under the text, such as suggestions.
default MessageListDownload A custom icon.

Keyboard

Keys Action
Tab Focuses the log, a scrollable region.
ArrowUp / ArrowDown Scroll the focused log. Scrolling up stops following new messages.
PageUp / PageDown Scroll by a page.
Home / End Jump to the oldest or newest message. End follows again.
Enter / Space On the scroll button: back to the newest message, following again; focus moves to the log as the button hides.

Data attributes

Attribute Values On
data-at-bottom present at the bottom .message-list
data-stuck present while following new content .message-list

Accessibility

  • The viewport is role=log (a polite live region) with an aria-label, so each new message is announced.
  • busy sets aria-busy while a reply streams; screen readers read the finished text instead of every token.
  • The viewport is focusable, so keyboard users can scroll the conversation.
  • The scroll button is named Scroll to latest and leaves the tab order while hidden.

See also