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
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. The pattern below renders a vertical stack of clickable rows, each with an icon, file name, and human-readable size — the same shape Slack, Discord, and Linear use for attached documents:
For developer apps wiring this to real Eloquent models, swap the inline <a> blocks for a @foreach($message->attachments as $attachment) loop and bind href="{{ $attachment->url }}" plus {{ $attachment->name }} / {{ $attachment->human_size }} accessors on the model.
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::url($message->attachment->path) 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 |
timestamp |
Carbon|string |
null |
Message timestamp |
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 |
Carbon|string|null |
null |
When the status was reached — adds a tooltip and an accessible "Read at 9:15 AM" text on the glyph. |
intent |
string |
'neutral' |
Bubble color intent: primary, neutral, info, success, warning, danger. primary and info render identically (both tint with --color-wk-accent). 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 |
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)- 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::alert>(status) or<x-wirekit::callout>(advice). The message component carries chat-specific semantics (author + timestamp).
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 + info / primary 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.