AI
AiMessageList
BitAiMessageList is the scrolling transcript of a BitAiConversation: every message of it, laid out by role through BitAiChatMessage, with auto-scroll that follows new content only while the reader is at the newest message - scrolling up to re-read is never yanked away - and, for long threads, only the newest messages drawn past a threshold, the older ones a page at a time as the reader scrolls up to them. It is the transcript BitAiChat renders, public for a chat assembled by hand.
Notes
Usage
Every example is live. Open its code to see exactly what produced the component running underneath.
Basic
It renders the transcript of a conversation: every message, laid out by role, in a column that scrolls.
Only while you are at the bottom. Scroll up to re-read and it leaves you where you are.
Session
It renders the transcript of a conversation: every message, laid out by role, in a column that scrolls.
Only while you are at the bottom. Scroll up to re-read and it leaves you where you are.
Templates
Message template
System messages
The written record of a conversation, in the order it was said.
Following the latest
Answer 1. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(18);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 5. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(26);
scheduler.Request();The interval is the only dial that matters.
Virtualization
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 173. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(42);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 177. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(50);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 181. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(18);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 185. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(26);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 189. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(34);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 193. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(42);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Answer 197. The cost is dominated by rendering, not by parsing. Coalescing updates removes most of it, and virtualization removes the rest.
Here is the shape of it:
var budget = TimeSpan.FromMilliseconds(50);
scheduler.Request();The interval is the only dial that matters.
- Render modes 94%
- Circuit lifetime 81%
Two passages matched, and they say the same thing.
| Messages | Rendered | Notes |
|---|---|---|
| 60 | all | below the threshold |
| 500 | visible only | virtualized |
Citations & feedback
On the server, for as long as the circuit lives. When the circuit drops, the state goes with it.
Disabled
It renders the transcript of a conversation: every message, laid out by role, in a column that scrolls.
Only while you are at the bottom. Scroll up to re-read and it leaves you where you are.
Cascading parameters
The written record of a conversation, in the order it was said.
The written record of a conversation, in the order it was said.
Style & Class
It renders the transcript of a conversation: every message, laid out by role, in a column that scrolls.
Only while you are at the bottom. Scroll up to re-read and it leaves you where you are.
It renders the transcript of a conversation: every message, laid out by role, in a column that scrolls.
Only while you are at the bottom. Scroll up to re-read and it leaves you where you are.
It renders the transcript of a conversation: every message, laid out by role, in a column that scrolls.
Only while you are at the bottom. Scroll up to re-read and it leaves you where you are.
RTL
متن کامل یک گفتگو را نشان میدهد: هر پیام به ترتیب، با چیدمان نقش خودش.
CSS variables
The public custom properties this component reads off its root, for what no parameter covers.
Every variable is read with a fallback and never declared by the component, so it inherits like any other custom property:
set one on :root (or in a [bit-theme] block) to restyle every instance, on any ancestor to restyle the ones inside it,
or on the Style of one instance to restyle it - and any instance nested inside it, which inherits the value too; a parameter changes one alone,
as does the real CSS property on the instance's Style / Styles when that property does not inherit (opacity: 1 keeps
one disabled instance undimmed without undimming a disabled one inside it), while an inherited one such as color or
font-family also reaches the nested instances that do not set it themselves. Leave a variable unset and the component
falls back to the theme token beside it.
BitAiMessageList CSS variables
| Name | Default value | Description |
|---|---|---|
| --bit-AiMessageList-max-width | spacing(92) | Width the column of messages stops growing at, centered in the list. A BitAiChat lines its composer up with it through --bit-AiChat-max-width: set both to the same value. |
| --bit-AiMessageList-gap | spacing(4), spacing(3) on a phone | Room between two messages. |
| --bit-AiMessageList-padding | spacing(3) spacing(2) spacing(2), spacing(2) spacing(1.5) spacing(1.5) on a phone | Inset of the column of messages. |
| --bit-AiMessageList-scrollbar-color | var(--bit-clr-brd-sec) | Thumb of the scrollbar of the list. |
API
Every parameter, public member, sub-class and enum this component exposes.
BitAiMessageList parameters
| Name | Type | Default value | Description |
|---|---|---|---|
| Classes | BitAiMessageListClassStyles? | null | Custom CSS classes for different parts of the message list. |
| Conversation | BitAiConversation | The conversation to render (required). The list subscribes to it for the messages added to and removed from it; passing another one starts that one at its newest message, without animating. | |
| EmptyTemplate | RenderFragment? | null | The content rendered instead of an empty list, while the conversation has no message to show - the system messages the list hides do not count. |
| FooterTemplate | RenderFragment? | null | The content rendered below the last message, inside the scroll area. |
| HeaderTemplate | RenderFragment? | null | The content rendered above the first message, inside the scroll area. Past BitAiUiOptions.VirtualizeThreshold messages it is drawn once the reader has scrolled up to the first message, along with it. |
| HideSystemMessages | bool | true | Hides the messages the user did not write and the model did not produce (the system and developer ones). Turned off, they are shown as a centered note. |
| MessageTemplate | RenderFragment<BitAiMessage>? | null | The template that replaces the built-in rendering of a message (a BitAiChatMessage). It is keyed by the message, so removing one message never recreates the ones after it, and it adds no element of its own around what it renders. The list draws it again as the newest message changes, so a template showing the text of a reply follows it as it streams. |
| OnCitationClick | EventCallback<BitAiCitation> | The callback for when the user activates a numbered citation in a reply. | |
| OnFeedback | EventCallback<BitAiMessageFeedback> | The callback for when the user records feedback on a reply, so a host can persist it. The message's Feedback is already updated when it is raised. | |
| OnPinnedChange | EventCallback<bool> | The callback for when the view stops or starts following the newest message: false when the user scrolls away from it (or, with BitAiUiOptions.AutoScroll off, when the newest message grows out of view), true when they scroll back to it or ScrollToLatestAsync brings them there. It is reported once per change, not on every scroll. | |
| OnSourceClick | EventCallback<BitAiCitationSource> | The callback for when the user activates a source card in the list of sources under a reply. | |
| Session | BitAiChatSession? | null | The session driving the conversation, which enables the message-level actions: editing a user message, regenerating the newest reply, retrying a failed one, deciding a tool approval. |
| Styles | BitAiMessageListClassStyles? | null | Custom CSS styles for different parts of the message list. |
BitAiMessageList public members
| Name | Type | Default value | Description |
|---|---|---|---|
| IsPinned | bool | true | Whether the reader is at the newest message, where the view follows new content (unless BitAiUiOptions.AutoScroll is off). |
| ScrollToLatestAsync | Task | Scrolls to the newest message and resumes following new content (raising OnPinnedChange with true, when the view was not following it). Its smooth argument (true by default) animates the scroll, unless the reader asked for reduced motion. |
BitComponentBase parameters
| Name | Type | Default value | Description |
|---|---|---|---|
| AriaLabel | string? | null | Gets or sets the accessible label for the component, used by assistive technologies. |
| Class | string? | null | Gets or sets the CSS class name(s) to apply to the rendered element. |
| Dir | BitDir? | null | Gets or sets the text directionality for the component's content. |
| Disabled | bool | false | Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction. |
| ForceAnimation | bool | false | Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested. |
| HtmlAttributes | Dictionary<string, object> | new Dictionary<string, object>() | Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. An attribute written on the component wins over an entry of the same name. |
| Id | string? | null | Gets or sets the unique identifier for the component's root element. |
| Style | string? | null | Gets or sets the CSS style string to apply to the rendered element. |
| TabIndex | string? | null | Gets or sets the tab order index for the component when navigating with the keyboard. |
| Visibility | BitVisibility | BitVisibility.Visible | Gets or sets the visibility state (visible, hidden, or collapsed) of the component. |
BitComponentBase public members
| Name | Type | Default value | Description |
|---|---|---|---|
| UniqueId | Guid | Guid.NewGuid() | Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed. |
| RootElement | ElementReference | Gets the reference to the root HTML element associated with this component. |
BitAiMessageListClassStyles properties
| Name | Type | Default value | Description |
|---|---|---|---|
| Root | string? | null | Custom CSS classes/styles for the root element (the scroll container) of the BitAiMessageList. |
| Content | string? | null | Custom CSS classes/styles for the content column of the BitAiMessageList, which holds the messages. |
BitAiConversation properties
An ordered set of messages plus the artifacts and agent runs that belong to the whole thread - the unit of state a chat UI binds to. Create one with new BitAiConversation(conversationId?) (an id is generated when none is given), fill it from history with AddMessage, and hand it to a session. It is observable at three grains: Changed for thread-level edits, MessageAdded / MessageRemoved for the list, and the events of each message for its content. Safe for one writer and concurrent readers.
| Name | Type | Default value | Description |
|---|---|---|---|
| ConversationId | string | The identifier of the conversation, given to its constructor or generated. | |
| Title | string? | null | The display title, set with SetTitle - or by a session with AutoTitle from the first user message. |
| Messages | IReadOnlyList<BitAiMessage> | [] | The messages, oldest first. |
| LastMessage | BitAiMessage? | null | The last message, or null when the conversation is empty. |
| IsGenerating | bool | false | True while the last message is pending or streaming. |
| CreatedAt / UpdatedAt | DateTimeOffset | When the conversation was created, and when it last changed. | |
| TotalUsage | BitAiTokenUsage | The token usage summed across every assistant message. | |
| Artifacts / Runs | IReadOnlyDictionary<string, BitAiArtifact> / IReadOnlyDictionary<string, BitAiAgentRun> | The artifacts produced and the agent runs made in this conversation, keyed by their identifiers. They belong to the thread rather than to a message, so a revision in a later turn updates the one artifact. | |
| Extensions | Dictionary<string, object?> | [] | Application-defined values attached to the conversation. |
| Version | int | 0 | A number that goes up on every change of the conversation, for a cheap check of whether anything changed since it was last read. |
| AddMessage(message) / AddMessage(role, text) | BitAiMessage | Appends a message - one built by hand, or one built from a role and its text - and returns it. | |
| RemoveMessage(messageId) | bool | Removes a message; true when one was removed. | |
| FindMessage(messageId) | BitAiMessage? | Finds a message by its identifier. | |
| TruncateAfter(messageId, inclusive?) | IReadOnlyList<BitAiMessage> | Removes every message after the given one (and that one too when inclusive is true) and returns them, newest first - how retry and edit rewind a thread. | |
| Clear() | void | Removes every message, with the artifacts and runs. | |
| SetTitle(title) | void | Sets the title of the conversation. | |
| GetOrAddArtifact(artifactId, kind, title) / FindArtifact(artifactId) | BitAiArtifact / BitAiArtifact? | Finds an artifact of the conversation, creating it with that kind and title when it does not exist yet - or only finds it, null when there is none. | |
| GetOrAddRun(runId) / FindRun(runId) | BitAiAgentRun / BitAiAgentRun? | Finds an agent run of the conversation, creating it when it does not exist yet - or only finds it, null when there is none. | |
| ToSummary() | BitAiConversationSummary | Projects the conversation into the shape a BitAiConversationList renders. | |
| Changed | event Action<BitAiConversation>? | Raised after a thread-level change, such as the title or an artifact. | |
| MessageAdded / MessageRemoved | event Action<BitAiConversation, BitAiMessage>? | Raised after a message is appended or inserted, and after one is removed - from whatever thread the stream is on. | |
| MessageUpdated | event Action<BitAiConversation, BitAiMessage>? | Raised when any message reports a change, structural or in one of its parts: convenient for a coarse observer such as an auto-save, while a component subscribes to the message itself. |
BitVisibility enum
| Name | Value | Description |
|---|---|---|
| Visible | 0 | The content of the component is visible. |
| Hidden | 1 | The content of the component is hidden, but the space it takes on the page remains (visibility:hidden). |
| Collapsed | 2 | The component is hidden (display:none). |
BitDir enum
| Name | Value | Description |
|---|---|---|
| Ltr | 0 | Ltr (left to right) is to be used for languages that are written from the left to the right (like English). |
| Rtl | 1 | Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic). |
| Auto | 2 | Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element. |
Feedback
Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.