AI
AiChat
BitAiChat is the whole chat surface in one component: the streaming transcript, the composer with attachments, slash commands and mentions, the empty state with its starter prompts, and the scroll-to-latest button, wired to a BitAiChatSession. Give it a session, or let it create one from the transport registered with AddBitBlazorUIAIServices - a working AI chat in one line of markup. Every part it composes is a public component of its own, so anything it does can also be assembled by hand.
Notes
Usage
Every example is live. Open its code to see exactly what produced the component running underneath.
Basic
Session
Conversation
In Bit.BlazorUI.AI, which builds on the core Bit.BlazorUI package.
Empty state
Templates
Composer
Custom composer
Attachments & commands
Submitting yourself
Message template
Citations & feedback
Options
Disabled
In Bit.BlazorUI.AI, which builds on the core Bit.BlazorUI package.
Cascading parameters
Style & Class
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.
BitAiChat CSS variables
| Name | Default value | Description |
|---|---|---|
| --bit-AiChat-background | var(--bit-clr-bg-pri) | Background of the chat, which the footer fades the last lines of the transcript into. |
| --bit-AiChat-max-width | spacing(92) | Width the composer stops growing at. Set --bit-AiMessageList-max-width to the same value to keep it lined up with the column of messages. |
| --bit-AiChat-footer-padding | 0 spacing(2) spacing(2), 0 spacing(1.5) spacing(1.5) on a phone | Inset of the footer around the composer. |
API
Every parameter, public member, sub-class and enum this component exposes.
BitAiChat parameters
| Name | Type | Default value | Description |
|---|---|---|---|
| AllowAttachments | bool | true | Offers attachments in the composer: files picked with its button, pasted or dropped onto it, up to MaxAttachmentSize each. |
| AllowDictation | bool | false | Offers dictation in the composer: a microphone button that transcribes speech into the text, shown only where the browser can recognize speech. |
| Classes | BitAiChatClassStyles? | null | Custom CSS classes for different parts of the chat. |
| Commands | IReadOnlyList<BitAiSlashCommand>? | null | The commands offered when the user types a forward slash in the composer. A command either inserts its Template into the text or runs its Handler. |
| ComposerHintTemplate | RenderFragment? | null | A hint rendered under the composer, such as the keys that send. |
| ComposerPrefixTemplate | RenderFragment? | null | The content placed before the text of the composer, such as a model picker. |
| ComposerSuffixTemplate | RenderFragment? | null | The content placed beside the send button of the composer. |
| ComposerTemplate | RenderFragment? | null | The content that replaces the whole composer. Whatever it holds submits through the session (ActiveSession) itself. |
| Conversation | BitAiConversation? | null | The conversation to show, such as one restored from history. Used only when no Session is supplied - a supplied session owns its own conversation. Passing another one switches the chat to it: the session the chat created for the old one is replaced. |
| EmptyBody | string? | null | The supporting line of the empty state. Defaults to the EmptyBody of the string table ("Ask a question to get started."). |
| EmptyTemplate | RenderFragment? | null | The content that replaces the empty state (and with it EmptyTitle, EmptyBody and Suggestions) while the conversation has no message to show - the system messages it hides do not count. |
| EmptyTitle | string? | null | The heading of the empty state. Defaults to the EmptyTitle of the string table ("How can I help?"). |
| FooterTemplate | RenderFragment? | null | The content below the composer, outside the scroll area, such as a disclaimer. |
| HeaderTemplate | RenderFragment? | null | The content above the transcript, outside the scroll area, such as a title bar. |
| HideSystemMessages | bool | true | Hides the system (and developer) messages from the transcript. Turned off, they are shown as a centered note. |
| ListFooterTemplate | RenderFragment? | null | The content at the bottom of the scroll area, below the last message. |
| ListHeaderTemplate | RenderFragment? | null | The content at the top of the scroll area, above the first message. Past BitAiUiOptions.VirtualizeThreshold messages it is drawn once the reader has scrolled up to the first message, along with it. |
| MaxAttachmentSize | long | 10485760 | The largest file the composer will stage, in bytes (10 MB by default). A larger one is turned away, the user is told, and OnAttachmentRejected is raised. |
| Mentions | IReadOnlyList<BitAiMentionItem>? | null | The items offered when the user types an at sign in the composer: files, people or data sources the application resolves by their Id later. A chosen one is inserted as @Label. |
| MessageTemplate | RenderFragment<BitAiMessage>? | null | The template that replaces how a message is rendered. It is keyed by the message and adds no element of its own; render a BitAiChatMessage inside it to keep the built-in streaming, parts and actions. |
| OnAttachmentRejected | EventCallback<BitAiAttachmentRejection> | The callback for each file the composer turns away (too large, of a type it does not take, one too many). The user is told either way; this is the same information for the application. | |
| 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 (thumbs up or down, or withdrawn), so a host can persist it. The message's Feedback is already updated when it is raised. | |
| OnSourceClick | EventCallback<BitAiCitationSource> | The callback for when the user activates a source card in the list of sources under a reply. | |
| OnSubmit | EventCallback<BitAiPromptSubmission> | The callback for when the user submits (the composer or a suggestion). Handle it to submit yourself - after uploading the attachments, or adding context to the text - through the session; leave it unset and the chat submits to the session. | |
| Placeholder | string? | null | The placeholder of the composer, which is also its accessible name. Defaults to the PromptPlaceholder of the string table ("Send a message..."). |
| Session | BitAiChatSession? | null | The session to drive. When unset, the chat creates one - through the registered BitAiChatSessionFactory, or over the registered IBitAiTransport - and disposes it with itself; a supplied session belongs to the page, which disposes it. |
| SessionOptions | BitAiChatSessionOptions? | null | The settings of a session this component creates. Ignored when a Session is supplied, which carries its own. Left null, the defaults configured with AddBitBlazorUIAIServices (ai.ConfigureSessions) apply. Options that name no Strings take the ones of the UI options in force, and SmoothStreaming off in those options drops their Pacing. |
| Styles | BitAiChatClassStyles? | null | Custom CSS styles for different parts of the chat. |
| Suggestions | IReadOnlyList<string>? | null | The example prompts offered in the empty state. A tap submits one as it is. |
| UiOptions | BitAiUiOptions? | null | The presentation settings of everything inside this chat (the string table, the render interval, what a message shows), in place of the ones a BitAiOptionsProvider cascades or AddBitBlazorUIAIServices registers - a whole record, not merged with them. A session the chat creates follows them too: its errors are worded in their Strings, and with SmoothStreaming off its text is not paced. |
BitAiChat public members
| Name | Type | Default value | Description |
|---|---|---|---|
| ActiveSession | BitAiChatSession | The session in use, whether supplied through Session or created by the chat. Reading it before the first render creates the chat's own session. | |
| ActiveConversation | BitAiConversation | The conversation in use, the one of ActiveSession. | |
| FocusComposerAsync | ValueTask | Puts the caret in the composer. Does nothing when a ComposerTemplate replaces it. |
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. |
BitAiChatClassStyles properties
| Name | Type | Default value | Description |
|---|---|---|---|
| Root | string? | null | Custom CSS classes/styles for the root element of the BitAiChat. |
| MessageList | BitAiMessageListClassStyles? | null | Custom CSS classes/styles for the BitAiMessageList (the transcript) of the BitAiChat. |
| EmptyState | BitAiEmptyStateClassStyles? | null | Custom CSS classes/styles for the BitAiEmptyState of the BitAiChat. |
| Footer | string? | null | Custom CSS classes/styles for the footer of the BitAiChat, which holds the composer. |
| FooterColumn | string? | null | Custom CSS classes/styles for the column inside the footer of the BitAiChat, which lines the composer up with the messages above it. |
| ScrollToLatest | BitAiScrollToLatestClassStyles? | null | Custom CSS classes/styles for the BitAiScrollToLatest of the BitAiChat. |
BitAiChatSession properties
Drives one conversation: submission, streaming, tool execution, approval, cancellation, retry and regeneration. Create one with the injected BitAiChatSessionFactory (Create(conversation, options)), which brings the registered transport, tools and approval policy, or with new BitAiChatSession(transport, conversation, options, ...). Submitting while a turn is in flight is a no-op. Dispose it (DisposeAsync) when the page goes: that cancels the turn in flight and detaches every handler.
| Name | Type | Default value | Description |
|---|---|---|---|
| Conversation | BitAiConversation | The conversation this session drives, given to its constructor or created with it. | |
| Options | BitAiChatSessionOptions | new() | The settings in force, given to its constructor. It is settable - assign a changed copy (session.Options with { ... }) - and each turn reads the ones in force as it starts. |
| Processor | BitAiConversationStreamProcessor | The reducer that applies the events of the transport to the conversation: it turns them into parts, tool calls, artifacts and agent steps. Its EventApplied event is raised for every event once it is applied, which suits logging and tracing. | |
| Strings | BitAiStrings | BitAiStrings.Default | The text of the errors the session writes itself: the Strings of its Options, else BitAiStrings.Default. |
| IsGenerating | bool | false | True while a turn is in flight. |
| LastError | BitAiError? | null | The failure of the last turn, cleared when a new turn starts. |
| SubmitAsync(text, attachments?, cancellationToken?) | Task<BitAiMessage?> | Appends a user message (the text may be empty when attachments carry the request) and generates a reply. Returns the assistant message, or null when a turn was already running. | |
| RegenerateAsync(messageId?, cancellationToken?) | Task<BitAiMessage?> | Regenerates an assistant message - the most recent one when no id is given - discarding it and everything after it. Returns the new assistant message, or null when there was no assistant message to regenerate or a turn was already running. | |
| RetryAsync(cancellationToken?) | Task<BitAiMessage?> | Retries the last turn after a failure: the failed assistant message is removed and the user message before it is answered again. Returns null when the conversation is empty or a turn was already running. | |
| EditAsync(messageId, text, cancellationToken?) | Task<BitAiMessage?> | Replaces the text of a user message and regenerates everything after it. Returns null when no user message of that id was found or a turn was already running. | |
| Stop() | void | Stops the current turn. The partial answer is kept and marked cancelled. Safe to call from any thread, and a no-op with no turn in flight. | |
| Approve(toolCallId, decision) | bool | Records a human decision (a BitAiApprovalDecision) on a tool call that is waiting for one. Returns false, changing nothing, when no call of that id is waiting - it has run, been decided or been cancelled, or is not known. | |
| RespondToAgentAsync(runId, answer, cancellationToken?) | Task<BitAiMessage?> | Answers a question an agent run is blocked on (appended as a user message), then continues the turn. Returns null when that run was not waiting for input or a turn was already running. | |
| StateChanged | event Action? | Raised whenever anything the UI cares about changes. Coarse by design and raised from whatever thread the stream is on: marshal it with InvokeAsync, and coalesce the renders it asks for. | |
| TurnCompleted | event Action<BitAiMessage>? | Raised when a turn ends, successfully or not, with its assistant message. | |
| ApprovalRequested | event Action<BitAiToolCallPart>? | Raised when a tool call needs a human decision. | |
| DisposeAsync() | ValueTask | Ends the session: cancels the turn in flight and any decision it waits for, and detaches every handler, so no event is raised after it. A session the page created is the page's to dispose; one a BitAiChat created, the chat disposes. |
BitAiChatSessionOptions properties
The settings of a BitAiChatSession, an immutable record. Every one has a defensible default: tools execute automatically, destructive ones ask first, and a runaway tool loop is bounded. AddBitBlazorUIAIServices sets the defaults of the sessions its factory creates (ai.ConfigureSessions).
| Name | Type | Default value | Description |
|---|---|---|---|
| AutoTitle | bool | true | Derives the title of the conversation from the first user message when it has none. |
| CatchTransportExceptions | bool | true | Whether a failed turn only leaves a retryable error on the assistant message, rather than throwing. Either way the message ends failed with the error on it; turned off, the exception also reaches the caller of the turn (SubmitAsync and the rest). |
| ExecuteTools | bool | true | Executes the tool calls of the model in the session. Turn it off when the transport runs the tools on the server and only reports them as events. |
| MaxToolRoundtrips | int | 10 | How many times the session feeds tool results back and asks the model again in one turn - the bound that keeps a model calling tools in a loop from spending without end. |
| Pacing | BitAiTextPacingOptions? | BitAiTextPacingOptions.Default | Evens out bursty text output so it renders at a steady rate. Null renders the deltas exactly as the transport produces them; contradicting settings throw when the options are built. |
| RequestOptions | BitAiRequestOptions? | null | The generation settings (the model, the temperature, the token limit, ...) passed to the transport on every request. |
| Strings | BitAiStrings? | null | The text of the errors the session writes itself: a stopped or timed-out turn, a declined tool call, the tool loop limit. Null uses the strings of the UI options in force where the session is created by the factory or a BitAiChat, else BitAiStrings.Default. |
| Timeout | TimeSpan? | null | How long to wait for the whole turn, tool round trips included. Null sets no limit beyond what the transport enforces. |
| ToolResultHoldTime | TimeSpan | 10 seconds | How long a tool result the transport reports ahead of the call it answers is held for that call to start. A call that starts in time is given the result and is not run again; when none has, the result is dropped, leaving an error part (code orphaned_tool_result, carrying a BitAiOrphanedToolResultException) on the message, and the session logs it. Zero drops such a result at once; a negative value throws when the options are built. |
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.