# MessageList A conversation that stays pinned to the newest message unless the reader scrolls up. ```ehtml Example import { MessageList, MessageListEmpty, MessageListDownload } from "@elements/ui/message-list"; import { Message, MessageContent, MessageResponse } from "@elements/ui/message"; m.id} from={m.role}> ``` ## 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` | `{}` | 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` | `{}` | 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` | `{}` | 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 - [Message](message): One chat message with avatar, author, time, streaming Markdown, attachments, actions and response branches. - [PromptInput](prompt-input): A growing message composer with attachments, tools, a model picker and a send button that stops a streaming reply. - [Attachment](attachment): A file or source as a thumbnail, chip or row, with preview, size, upload progress and remove.