Componentmessage
Message
Displays a message in a conversation, with optional avatar, header, footer, and alignment.
Preview
Displays a message in a conversation, with optional avatar, header, footer, and alignment.
@ui.Message(ui.MessageProps{Align: "start"}) {
@ui.MessageAvatar(ui.DOMProps{}) {
@ui.Avatar(ui.AvatarProps{Class: "size-8"}) {
@ui.AvatarFallback(ui.DOMProps{}) { R }
}
}
@ui.MessageContent(ui.DOMProps{}) {
@ui.Bubble(ui.BubbleProps{Variant: "muted"}) {
@ui.BubbleContent(ui.DOMProps{}) { The build failed during dependency installation. }
}
}
}Installation
Add this component to your project using the CLI.
templcn add messageUsage
1. Import the component in your Go or templ file:
import "your-module/ui"2. Use the component in your template:
@ui.Message(ui.MessageProps{Align: "start"}) {
@ui.MessageAvatar(ui.DOMProps{}) {
@ui.Avatar(ui.AvatarProps{Class: "size-8"}) {
@ui.AvatarFallback(ui.DOMProps{}) { R }
}
}
@ui.MessageContent(ui.DOMProps{}) {
@ui.Bubble(ui.BubbleProps{Variant: "muted"}) {
@ui.BubbleContent(ui.DOMProps{}) { The build failed during dependency installation. }
}
}
}Composition
Use these parts together to build the component.
Message
├── MessageAvatar
├── Avatar
├── AvatarFallback
├── MessageContent
├── Bubble
├── BubbleContentExamples
Named examples and common variations.
Avatar
Render incoming and outgoing message rows with sender avatars.
@ui.Message(ui.MessageProps{Align: "start"}) {
@ui.MessageAvatar(ui.DOMProps{}) {
@ui.Avatar(ui.AvatarProps{Class: "size-8"}) {
@ui.AvatarFallback(ui.DOMProps{}) { R }
}
}
@ui.MessageContent(ui.DOMProps{}) {
@ui.Bubble(ui.BubbleProps{Variant: "muted"}) {
@ui.BubbleContent(ui.DOMProps{}) { The build failed during dependency installation. }
}
}
}
@ui.Message(ui.MessageProps{Align: "end"}) {
@ui.MessageAvatar(ui.DOMProps{}) {
@ui.Avatar(ui.AvatarProps{Class: "size-8"}) {
@ui.AvatarFallback(ui.DOMProps{}) { ME }
}
}
@ui.MessageContent(ui.DOMProps{}) {
@ui.Bubble(ui.BubbleProps{Variant: "default"}) {
@ui.BubbleContent(ui.DOMProps{}) { Can you share the exact error? }
}
}
}Group
Stack consecutive messages from the same sender using MessageGroup.
@ui.MessageGroup(ui.DOMProps{}) {
@ui.Message(ui.MessageProps{Align: "start"}) {
@ui.MessageAvatar(ui.DOMProps{})
@ui.MessageContent(ui.DOMProps{}) {
@ui.Bubble(ui.BubbleProps{Variant: "muted"}) {
@ui.BubbleContent(ui.DOMProps{}) { I checked the registry addresses. }
}
}
}
@ui.Message(ui.MessageProps{Align: "start"}) {
@ui.MessageAvatar(ui.DOMProps{}) {
@ui.Avatar(ui.AvatarProps{Class: "size-8"}) {
@ui.AvatarFallback(ui.DOMProps{}) { CN }
}
}
@ui.MessageContent(ui.DOMProps{}) {
@ui.Bubble(ui.BubbleProps{Variant: "muted"}) {
@ui.BubbleContent(ui.DOMProps{}) { The component and example JSON now live under the UI registry. }
}
}
}
}Header & Footer
Add sender titles, delivery status, and message-level actions.
@ui.Message(ui.MessageProps{Align: "start"}) {
@ui.MessageContent(ui.DOMProps{}) {
@ui.MessageHeader(ui.DOMProps{}) { Olivia }
@ui.Bubble(ui.BubbleProps{Variant: "muted"}) {
@ui.BubbleContent(ui.DOMProps{}) { I already checked the logs. }
}
}
}
@ui.Message(ui.MessageProps{Align: "end"}) {
@ui.MessageContent(ui.DOMProps{}) {
@ui.Bubble(ui.BubbleProps{Variant: "default"}) {
@ui.BubbleContent(ui.DOMProps{}) { Send the report to the team. Ping @shadcn if you need help. }
}
@ui.MessageFooter(ui.DOMProps{}) { Read Yesterday }
}
}API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| Align | string | "start" | "start" (receiver) or "end" (sender). |
View source
package ui
import (
"context"
"github.com/a-h/templ"
"io"
)
type MessageProps struct {
DOMProps
Align string
}
func MessageGroup(props DOMProps) templ.Component {
return messageBlock("message-group", "flex min-w-0 flex-col gap-2", "div", props)
}
func Message(props MessageProps) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
align := props.Align
if align == "" {
align = "start"
}
attrs := attrsFromDOMProps(props.DOMProps, "message", "group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse")
attrs["data-align"] = align
return renderElement(ctx, w, "div", attrs, templ.GetChildren(ctx))
})
}
func MessageAvatar(props DOMProps) templ.Component {
return messageBlock("message-avatar", "flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8", "div", props)
}
func MessageContent(props DOMProps) templ.Component {
return messageBlock("message-content", "flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end", "div", props)
}
func MessageHeader(props DOMProps) templ.Component {
return messageBlock("message-header", "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0", "div", props)
}
func MessageFooter(props DOMProps) templ.Component {
return messageBlock("message-footer", "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end", "div", props)
}
func messageBlock(slot, className, tag string, props DOMProps) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
return renderElement(ctx, w, tag, attrsFromDOMProps(props, slot, className), templ.GetChildren(ctx))
})
}