Message
A chat message bubble with author metadata, timestamp, side-based alignment, and slots for reactions and attachments. Designed for chat interfaces and comment threads.
Basic Usage
With Timestamp
Side Alignment
Use side="right" for outgoing messages (current user):
With Avatar
Without an avatar, the bubble shows the initials of the name: the first letter of the first and of the last word, in the color those letters always get. Senders without a picture no longer all look the same, and each one keeps their color wherever they appear. When those letters are not how someone is known, pass your own as initials.
Author Role Badge
Edited Indicator
System Messages with Intent
Use intent variants for system-generated messages:
With Reactions
With File Attachments
Attach files inline beneath the message text. <x-wirekit:: stacks the rows and names them for assistive technology; each <x-wirekit:: renders the file glyph, the name, and a human-readable size and type it derives itself — pass the raw byte count and the MIME type, never a pre-formatted string:
For developer apps wiring this to real Eloquent models, wrap the attachments in a @foreach($message->attachments as $attachment) loop and bind :bytes="$attachment->size", :type="$attachment->mime_ and href="{{ $attachment->url }}". There is no human_size accessor to write — the component formats the byte count and the type label itself.
With Image in Chat
For chat-style image previews, drop a placeholder <img> straight into the message body at a constrained max-width. The bubble auto-sizes around the image, and the rounded corners on the image match the message bubble's radius for a polished look:
Use loading="lazy" on inline chat images so a long thread doesn't trigger network fetches for messages that haven't scrolled into view. Pin the rendered width (or max-width) inline so the image doesn't blow past the message column when the source asset is wider than the chat layout — the height: auto keeps the natural aspect ratio. For real apps, replace the /placeholder/... URL with Storage:: or a signed CDN URL.
Delivery status
status renders the delivery ladder for a message you sent. Every rung carries
its own wording — the glyph and color are support, never the only signal.
The glyph follows the convention every messaging app shares: one check =
sent to the server, two checks = delivered to the recipient, two accent
checks = read. failed shows its text on screen because it needs the user to
act; the rest announce to assistive technology.
{{-- 1. Bind the rung to whatever your model already tracks --}}
<x-wirekit::message :author="$me" side="right" :status="$message->delivery_status">
{{ $message->body }}
</x-wirekit::message>
Pair failed with a retry control in the actions slot.
Delivery time
Pass statusTime and the status glyph carries a tooltip with the exact moment —
"Read at 9:15 AM". The time is also woven into the glyph's accessible text, so a
screen reader hears it without the (mouse-only) hover. Hover the checks below:
Props
| Prop | Type | Default | Description |
|---|---|---|---|
author |
array |
[] |
Author data: name, avatar (URL), role, and initials, which replaces the letters derived from name when there is no avatar |
timestamp |
DateTimeInterface|string |
null |
Message timestamp: a date object of any class or a string |
timeFormat |
string|null |
null |
Carbon format string for the timestamp. Default renders the locale-aware short time (9:15 PM for English, 21:15 for German and other 24-hour locales). Pass e.g. H:i to force a format. |
side |
string |
'left' |
Alignment: left (incoming) or right (outgoing) |
status |
string|null |
null |
Delivery status for a sent message: 'sending', 'sent', 'delivered', 'read', 'failed'. Each rung carries its own text — never conveyed by color alone. |
statusTime |
DateTimeInterface|string|null |
null |
When the status was reached — adds a tooltip and an accessible "Read at 9:15 AM" text on the glyph. |
timezone |
string|null |
null |
The zone the timestamp and the status time are written in for the reader, such as Europe/Berlin. Defaults to the zone of the value, which for a date from the database is usually UTC. |
intent |
string |
'neutral' |
Bubble color intent: primary, neutral, info, success, warning, danger. primary tints with --color-wk-accent and info with --color-wk-info-tone, which is the accent until you give info a color of its own. See Variants & Intents for the cross-component reference. |
actionsReveal |
string |
'hover' |
How the actions slot is revealed: hover (visible on hover or keyboard focus) or always (always visible — the accessible choice for touch devices, which have no hover). |
edited |
bool |
false |
Show "(edited)" indicator |
scope |
string|null | null |
Scoped personalization name |
Slots
| Slot | Description |
|---|---|
| default | Message body content |
reactions |
Reaction buttons below the bubble |
attachments |
File or media attachments |
actions |
Hover-revealed action menu |
Accessibility
<article role="article">root elementaria-labelledbylinks to the message header (author + timestamp). Two messages from the same author at the same time get their own header ids, the second ending in-2- Semantic
<time>element with ISOdatetimeattribute - Bubble width capped at
42chfor readability
Keyboard Interaction
This component is purely presentational and does not respond to keyboard input.
Pitfalls
- Don't use message in non-chat contexts. Reach for
<x-wirekit::(status) oralert> <x-wirekit::(advice). The message component carries chat-specific semantics (author + timestamp).callout>
Design Tokens
| Token | Used for |
|---|---|
--font-wk-sans |
Bubble font family |
--font-wk-heading-weight |
Author name weight |
--text-wk-sm / --text-wk-md |
Header / body font size |
--color-wk-text |
Message body text |
--color-wk-text-muted |
Timestamp + edited indicator |
--color-wk-accent |
Right-side bubble tint + primary intent tint |
--color-wk-info-tone |
info intent tint |
--color-wk-success |
success intent tint |
--color-wk-warning |
warning intent tint |
--color-wk-danger |
danger intent tint |
--color-wk-bg-elevated |
Bubble background base |
--color-wk-border / --color-wk-border-subtle |
Bubble border (intent-tinted for non-neutral, subtle for chat bubbles) |
--border-wk-width |
Bubble border width |
--radius-wk-lg |
Bubble border radius |
--transition-wk-duration |
Hover-action fade |
Usage & Conventions
Prop conventions — this component uses one or more of the shared semantic prop names (
intent/variant/tone/surface). See Prop naming conventions for the canonical vocabulary, alias matrix, and decision tree.