# AiMessageActions
## Description
BitAiMessageActions is the row under a finished assistant message: copy, regenerate (with a session, for the newest reply) and thumbs up or down feedback, plus extra buttons of the app's own, and the metadata the BitAiUiOptions in force choose to show - the model, the token usage, the time. The actions are revealed while the message is hovered or holds the focus; the metadata is always shown. BitAiChatMessage renders one under every reply.
## Parameters
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| CanRegenerate | `bool` | true | Offers regeneration of the message, when a Session is given. Only the newest assistant message should offer it, since regenerating an older one discards everything after it; a BitAiChatMessage sets it from its IsLatest. |
| Classes | `BitAiMessageActionsClassStyles?` | null | Custom CSS classes for different parts of the message actions. |
| ExtraActionsTemplate | `RenderFragment?` | null | The extra buttons appended to the row of actions, after the feedback buttons. They are revealed and hidden with the built-in ones, and left out with them when the ShowMessageActions of the options in force is off. |
| Message | `BitAiMessage` | | The message these actions belong to (required): what copy copies, what feedback is recorded on, and where the model, the usage and the time are read from. |
| OnFeedback | `EventCallback<BitAiFeedbackKind>` | | The callback for when the user records feedback, so a host can persist it: Positive or Negative, or None when the user pressed the chosen one again to withdraw it. The message's Feedback is already updated when it is raised. A BitAiChatMessage (and the BitAiMessageList and BitAiChat around it) reports the same choice through its own OnFeedback as a BitAiMessageFeedback, which pairs it with the message (see the BitAiChatMessage page). |
| Pinned | `bool` | false | Keeps the actions visible rather than revealing them while the message is hovered or holds the focus. |
| Session | `BitAiChatSession?` | null | The session driving the conversation of the message, which enables regeneration. |
| ShowFeedback | `bool` | true | Shows the thumbs up and thumbs down buttons. |
| Styles | `BitAiMessageActionsClassStyles?` | null | Custom CSS styles for different parts of the message actions. |
| 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. |
## 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. |
## Enums
### BitAiFeedbackKind Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| None | 0 | No feedback given, or the feedback was withdrawn. |
| Positive | 1 | The response was helpful (thumbs up). |
| Negative | 2 | The response was not helpful (thumbs down). |
### 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. |
## Sub Classes
### BitAiMessageActionsClassStyles Properties
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Root | `string?` | null | Custom CSS classes/styles for the root element of the BitAiMessageActions. |
| Actions | `string?` | null | Custom CSS classes/styles for the group of action buttons of the BitAiMessageActions. |
| RegenerateButton | `BitButtonClassStyles?` | null | Custom CSS classes/styles for the regenerate button of the BitAiMessageActions. |
| FeedbackButton | `BitButtonClassStyles?` | null | Custom CSS classes/styles for the two feedback buttons of the BitAiMessageActions. |
| Model | `string?` | null | Custom CSS classes/styles for the model name of the BitAiMessageActions. |
| Time | `string?` | null | Custom CSS classes/styles for the time of the BitAiMessageActions. |
## CSS Variables
Public CSS custom properties read off the component's root. Set one on `:root` to restyle every instance, on any ancestor to restyle the ones inside it, or on the `Style` of one instance to restyle it and every instance nested inside it, which inherits the value too - a parameter changes one alone, as does the real CSS property on its `Style` / `Styles` when that property does not inherit (`opacity`); an inherited one (`color`, `font-family`) reaches the nested instances that do not set it themselves.
| Name | Default Value | Description |
| :--- | :------------ | :---------- |
| `--bit-AiMessageActions-gap` | spacing(1.5) | Room between the group of actions and each piece of metadata. |
| `--bit-AiMessageActions-actions-gap` | spacing(0.5) | Room between two action buttons. |
| `--bit-AiMessageActions-color` | var(--bit-clr-fg-ter) | Text of the metadata: the model, the usage and the time. |
| `--bit-AiMessageActions-font-size` | var(--bit-tpg-fs-xs) | Size of the metadata. |
## Examples
\n**Basic**:
```razor
```
```csharp
private readonly BitAiMessage message = CreateReply("A finished reply. Hover this row to reveal its actions.");
// A finished reply with what a provider reports about it: the model and the token usage.
private static BitAiMessage CreateReply(string text)
{
var message = new BitAiMessage(BitAiRole.Assistant);
message.AddPart(new BitAiTextPart(text));
message.MergeMetadata(new BitAiGenerationMetadata
{
ModelId = "demo-model-1",
Usage = new BitAiTokenUsage { InputTokens = 42, OutputTokens = 96 },
});
return message;
}
```
\n**Pinned**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private readonly BitAiMessage pinnedMessage = CreateReply("A reply whose actions are always shown.");
```
\n**Feedback**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private BitAiFeedbackKind lastFeedback;
private readonly BitAiMessage feedbackMessage = CreateReply("Was this answer helpful?");
private readonly BitAiMessage noFeedbackMessage = CreateReply("A reply that does not ask for feedback.");
private void HandleFeedback(BitAiFeedbackKind feedback)
{
lastFeedback = feedback;
}
```
\n**Regenerate**:
```razor
@implements IAsyncDisposable
@if (regenerateSession.Conversation.LastMessage is { } reply)
{
@if (reply.IsBusy)
{
}
}
```
```csharp
// CreateReply is the helper of the Basic example.
private bool canRegenerate = true;
// A transport that echoes the prompt, over a conversation that already has a reply.
private readonly BitAiChatSession regenerateSession = new(AiDemoTransports.Echo(), CreateRegenerateConversation());
private static BitAiConversation CreateRegenerateConversation()
{
var conversation = new BitAiConversation();
conversation.AddMessage(BitAiRole.User, "Say something.");
conversation.AddMessage(CreateReply("Press regenerate and this reply is written again."));
return conversation;
}
protected override void OnInitialized()
{
regenerateSession.Conversation.MessageAdded += OnRegenerateMessageAdded;
regenerateSession.TurnCompleted += OnRegenerateTurnCompleted;
}
// A regenerate replaces the reply: the new one is added, streams, and the turn completes.
private void OnRegenerateMessageAdded(BitAiConversation conversation, BitAiMessage message) => _ = InvokeAsync(StateHasChanged);
private void OnRegenerateTurnCompleted(BitAiMessage message) => _ = InvokeAsync(StateHasChanged);
public async ValueTask DisposeAsync()
{
regenerateSession.Conversation.MessageAdded -= OnRegenerateMessageAdded;
regenerateSession.TurnCompleted -= OnRegenerateTurnCompleted;
await regenerateSession.DisposeAsync();
}
```
\n**Extra actions**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private bool isBookmarked;
private readonly BitAiMessage extraMessage = CreateReply("A reply with a bookmark button of the app's own.");
private void ToggleBookmark()
{
isBookmarked = isBookmarked is false;
}
```
\n**Options**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private readonly BitAiUiOptions allMetadataOptions = new() { ShowModelName = true, ShowUsage = true, ShowTimestamps = true };
private readonly BitAiUiOptions metadataOnlyOptions = new() { ShowModelName = true, ShowUsage = true, ShowMessageActions = false };
private readonly BitAiMessage optionsMessage = CreateReply("The model, the usage and the time.");
private readonly BitAiMessage metadataOnlyMessage = CreateReply("The metadata alone, without the actions.");
```
\n**Disabled**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private bool isDisabled = true;
private readonly BitAiMessage disabledMessage = CreateReply("A reply whose actions are disabled.");
```
\n**Cascading parameters**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private readonly BitAiMessageActionsParams[] actionsParams = [new() { Pinned = true, ShowFeedback = false }];
private readonly BitAiMessage cascadeMessage = CreateReply("Pinned, without feedback, from the BitParams around it.");
private readonly BitAiMessage cascadeOwnMessage = CreateReply("Pinned from the BitParams, with its own ShowFeedback.");
```
\n**Style & Class**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private readonly BitAiMessage styleMessage = CreateReply("Styled.");
private readonly BitAiMessage classMessage = CreateReply("Classy.");
private readonly BitAiMessage variablesMessage = CreateReply("Restyled by its variables.");
```
\n**RTL**:
```razor
```
```csharp
// CreateReply is the helper of the Basic example.
private readonly BitAiMessage rtlMessage = CreateReply("پاسخی که دکمههایش همیشه نمایش داده میشوند.");
```
@message.GetText()
@pinnedMessage.GetText()
@feedbackMessage.GetText()
Last feedback: @lastFeedback
@noFeedbackMessage.GetText()
Regenerating...
}
else
{
@reply.GetText()
@extraMessage.GetText()
@optionsMessage.GetText()
@metadataOnlyMessage.GetText()
@disabledMessage.GetText()
@cascadeMessage.GetText()
@cascadeOwnMessage.GetText()
@rtlMessage.GetText()