Skip to main content
twblazor
Home
  • Get started
  • Tailwind with Blazor
  • Why twblazor?
  • Theme
  • Class Merge
    • Configuring localization
    • RTL Provider
  • Breadcrumb
  • Card
  • Carousel
  • Collapse
  • Footer
  • MenuNew
  • Navbar
  • On This PageNew
  • Sidebar
  • Stepper
  • Tabs
  • Tree List
  • AutocompleteNew
  • Button
  • Checkbox
  • Color Picker
    • Date
    • Date Range
    • Datetime
    • Datetime Range
    • Time
    • Time Range
  • File Upload
  • NumericNew
  • Radio Button
  • RatingNew
  • Select
  • Slider
  • Switch
  • Textfield
  • Alert
  • Avatar
  • Chip
  • Icon
  • Progress
  • Skeleton
  • Spinner
  • TooltipNew
  • Data Table
  • Pagination
  • Pick List
  • BarcodeNew
  • QR CodeNew
  • CalendarNew
  • Table
  • AttachmentNew
  • Overview
  • Area
  • Bar
  • Box Plot
  • Bullet
  • Bump
  • Candlestick
  • Column
  • Dot Plot
  • Dumbbell
  • Funnel
  • Gantt
  • Gauge
  • Heatmap
  • Histogram
  • Icon
  • Line
  • Lollipop
  • Matrix
  • Nightingale
  • Parallel Coordinates
  • Pie
  • Quadrant
  • Radar
  • Radial Bar
  • Range
  • Scatter
  • Slope
  • Small Multiples
  • Strip Plot
  • Treemap
  • Waffle
  • Waterfall
  • Arc Diagram
  • Barcode
  • Beeswarm
  • Bump Area
  • Categorical Scatter
  • Chord Diagram
  • Circular Treemap
  • Contour
  • Convex Treemap
  • Density Plot
  • Dendrogram
  • Euler Diagram
  • Flowchart
  • Hexagonal Binning
  • Horizon
  • Marimekko
  • Network Diagram
  • Radial Histogram
  • Ridgeline
  • Sankey
  • Stream Graph
  • Sunburst
  • Venn Diagram
  • Violin Plot
  • Word Cloud
  • Bubble
  • Marker
  • Message
  • Dialog Service
  • Toast Service
API DocumentationAI Agents & Skills
Home Get Started

Chat

TwMessage

TwMessage is a Blazor chat message row with an avatar, the author, the time, the message content and a footer, aligned to the start or end of a conversation.

Last updated 20 October 2026

Please be aware this component is new, may have bugs and/or be subject to change. Please report any bugs at https://github.com/twblazor/twblazor/issues.

Basic usage

Give TwMessage an Author and a Timestamp, and put the message itself in a TwBubble. The avatar shows the author's initials. Wrap the conversation in a container with role="log" so screen readers announce new messages.
JD
Jane Doe9:30 AM
Has the release gone out yet?
SL
Sam Lee9:32 AM
Not yet, the last build is still running.
RAZOR
<div role="log" aria-label="Conversation" class="flex flex-col gap-6">
    <TwMessage Author="Jane Doe" Timestamp="@_sentAt">
        <TwBubble>Has the release gone out yet?</TwBubble>
    </TwMessage>
    <TwMessage Author="Sam Lee" Timestamp="@_sentAt.AddMinutes(2)" AvatarColor="Color.Primary">
        <TwBubble>Not yet, the last build is still running.</TwBubble>
    </TwMessage>
</div>
CSHARP
@code {
    private readonly DateTime _sentAt = new(2026, 10, 19, 9, 30, 0, DateTimeKind.Local);
}

Your own messages

Set Align to MessageAlign.End for the current user's messages. The avatar moves to the end edge, and any TwBubble inside follows the alignment and points its tip at the avatar.
Assistant9:30 AM
How can I help today?
Y
You9:31 AM
Summarise yesterday's support tickets, please.
RAZOR
<div role="log" aria-label="Conversation" class="flex flex-col gap-6">
    <TwMessage Author="Assistant" AvatarIcon="Icon.Robot" AvatarColor="Color.Info" Timestamp="@_sentAt">
        <TwBubble>How can I help today?</TwBubble>
    </TwMessage>
    <TwMessage Author="You" Align="MessageAlign.End" Timestamp="@_sentAt.AddMinutes(1)" AvatarColor="Color.Primary">
        <TwBubble Variant="BubbleVariant.Filled">Summarise yesterday's support tickets, please.</TwBubble>
    </TwMessage>
</div>
CSHARP
@code {
    private readonly DateTime _sentAt = new(2026, 10, 19, 9, 30, 0, DateTimeKind.Local);
}

Continued messages

Set Continued on a message that follows another from the same author. Its avatar and header are hidden from view so the messages read as one group, but the author and time are still read out to screen readers.
JD
Jane Doe9:30 AM
Quick update on the launch.
Jane Doe9:30 AM
The copy is signed off.
Jane Doe9:31 AM
Images are going in this afternoon.
RAZOR
<div role="log" aria-label="Conversation" class="flex flex-col gap-2">
    <TwMessage Author="Jane Doe" Timestamp="@_sentAt">
        <TwBubble>Quick update on the launch.</TwBubble>
    </TwMessage>
    <TwMessage Author="Jane Doe" Timestamp="@_sentAt" Continued>
        <TwBubble Tail="false">The copy is signed off.</TwBubble>
    </TwMessage>
    <TwMessage Author="Jane Doe" Timestamp="@_sentAt.AddMinutes(1)" Continued>
        <TwBubble Tail="false">Images are going in this afternoon.</TwBubble>
    </TwMessage>
</div>
CSHARP
@code {
    private readonly DateTime _sentAt = new(2026, 10, 19, 9, 30, 0, DateTimeKind.Local);
}

Footer

Use Footer for actions or a delivery state under the message. Give icon buttons an AriaLabel.
Assistant9:30 AM
Here is a draft reply for the customer.
Copy Regenerate Generated in 2.1s
RAZOR
<TwMessage Author="Assistant" AvatarIcon="Icon.Robot" AvatarColor="Color.Info" Timestamp="@_sentAt">
    <ChildContent>
        <TwBubble>Here is a draft reply for the customer.</TwBubble>
    </ChildContent>
    <Footer>
        <TwIcon Icon="Icon.Clipboard" AriaLabel="Copy reply" Tooltip="Copy" OnClick="@(() => { })" />
        <TwIcon Icon="Icon.Arrow_Clockwise" AriaLabel="Regenerate reply" Tooltip="Regenerate" OnClick="@(() => { })" />
        <span>Generated in 2.1s</span>
    </Footer>
</TwMessage>
CSHARP
@code {
    private readonly DateTime _sentAt = new(2026, 10, 19, 9, 30, 0, DateTimeKind.Local);
}

An assistant conversation

The chat components work together: TwMarker for the steps an assistant took and for date separators, TwAttachment for files, and TwBubble reactions for feedback.
Today
Y
You9:30 AM
q3-sales.xlsx47.1 KB · XLSX
Which region grew the most last quarter?
Assistant9:31 AM
Read q3-sales.xlsx0.4sDone
Compared regions1.2sDone
The North region grew the most, with sales up 18% on the quarter before.
RAZOR
<div role="log" aria-label="Conversation with the assistant" class="flex flex-col gap-6">
    <TwMarker Variant="MarkerVariant.Separator" Label="Today" />
    <TwMessage Author="You" Align="MessageAlign.End" Timestamp="@_sentAt" AvatarColor="Color.Primary">
        <TwAttachment FileName="q3-sales.xlsx" FileSize="48_230" />
        <TwBubble Variant="BubbleVariant.Filled">Which region grew the most last quarter?</TwBubble>
    </TwMessage>
    <TwMessage Author="Assistant" AvatarIcon="Icon.Robot" AvatarColor="Color.Info" Timestamp="@_sentAt.AddMinutes(1)">
        <TwMarker Status="MarkerStatus.Succeeded" Label="Read q3-sales.xlsx" Detail="0.4s" />
        <TwMarker Status="MarkerStatus.Succeeded" Label="Compared regions" Detail="1.2s" />
        <TwBubble Reactions="@_reactions" OnReactionClick="ToggleReaction">The North region grew the most, with sales up 18% on the quarter before.</TwBubble>
    </TwMessage>
</div>
CSHARP
@code {
    private readonly List<BubbleReaction> _reactions =
    [
        new() { Emoji = "👍", Label = "Helpful", Count = 2 },
        new() { Emoji = "👎", Label = "Not helpful", Count = 0 }
    ];
    
    private static void ToggleReaction(BubbleReaction reaction)
    {
        reaction.Reacted = !reaction.Reacted;
        reaction.Count += reaction.Reacted ? 1 : -1;
    }
}

Accessibility

Each message is an article named by its author and time, so screen reader users can jump from message to message. The avatar is decoration, since the author's name is written beside it. A continued message keeps its author and time for screen readers. Put the conversation in a container with role="log" and an aria-label, so new messages are announced politely as they arrive.

Keyboard navigation

A message is not a Tab stop. Each message is an article named by its author and time, so screen readers can move between messages with their article shortcut. Anything interactive inside a message, such as reactions or actions in its footer, keeps its own keyboard behaviour.

Theme configuration

Styling is controlled by TwBlazorTheme.Components (a TwMessageTheme), configured via the AddTwBlazor() options callback described on the Get Started page. Every property is a set of Tailwind classes, so changes are picked up by your own Tailwind build.
Property Type Controls
Base string
AvatarSpacer string
Content string
Header string
Author string
Timestamp string
Footer string

Full reference: TwMessageTheme on the API docs.

On this page

  • Basic usage
  • Your own messages
  • Continued messages
  • Footer
  • An assistant conversation
  • Accessibility
  • Keyboard navigation
  • Theme configuration
Discord (opens in a new tab) • GitHub (opens in a new tab) • Documentation (opens in a new tab) • MIT License (opens in a new tab) • llms.txt (opens in a new tab)

twblazor is and always will be free and open source.

An unhandled error has occurred. Reload