With Events
A day break and a model switch.
const yesterday = new Date(2026, 9, 3);
<ConversationList>
<ConversationList.Event date={yesterday} />
<Message from="user">
<Message.Content>Check main.</Message.Content>Follows new messages at the end, preserving position during scrolling and history loading.
const reply = "Two files need updated imports.";
<ConversationList>
<Message from="user">
<Message.Content>Which files break the workspace rules?</Message.Content>
</Message>pnpm add @usefragments/uiThe npm package stays managed by your package manager. Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.
Import ConversationList once, then compose its parts with dot notation.
ConversationList.EventA day break and a model switch.
const yesterday = new Date(2026, 9, 3);
<ConversationList>
<ConversationList.Event date={yesterday} />
<Message from="user">
<Message.Content>Check main.</Message.Content>The indicator sits last until the reply starts.
const waiting = true;
const messages = [<Message key="question" from="user"><Message.Content>Check main.</Message.Content></Message>];
<ConversationList>
{messages}
{waiting && <ThinkingIndicator label="Reading the request…" />}Earlier messages load at the top; the reader's place holds.
const loading = true;
const loadEarlier = () => {};
const messages = [<Message key="question" from="user"><Message.Content>Check main.</Message.Content></Message>];
<ConversationList onScrollTop={loadEarlier} history={loading ? "loading" : "idle"}>
{messages}A failed load says so and offers Retry.
const loadEarlier = () => {};
const messages = [<Message key="question" from="user"><Message.Content>Check main.</Message.Content></Message>];
<ConversationList history="error" onRetryHistory={loadEarlier}>
{messages}
</ConversationList>A first-run state when there are no messages.
<ConversationList
emptyState={<EmptyState><EmptyState.Title>Ask about your design system</EmptyState.Title></EmptyState>}
>
{[]}
</ConversationList>Prop | Type | Default | Description |
|---|---|---|---|
autoScroll | AutoScrollBehavior | undefined | smart | smart follows new content while the reader is at the end; false never moves the reader |
childrenRequired | React.ReactNode | Not set | Messages, events and the thinking indicator |
emptyState | React.ReactNode | Not set | What shows when there are no messages |
Event.children | React.ReactNode | Not set | What happened (a model switch, a joined user). Wins over `date`. |
Event.date | Date | undefined | Not set | A date for a day break; formatted as Today, Yesterday or the date. |
Event.format | ((date: Date) => string) | undefined | Not set | Custom date format. |
history | ConversationHistory | undefinedidleloadingerror | idle | Where earlier messages stand: idle, loading (a status line) or error (an errbox with Retry) |
label | string | undefined | Conversation | Accessible name of the log |
onRetryHistory | (() => void) | undefined | Not set | Retry loading earlier messages after history=error |
onScrollTop | (() => void) | undefined | Not set | Called when the reader reaches the top, to load earlier messages |
onScroll | UIEventHandler<HTMLDivElement> | undefined | Not set | — |