Skip to content
Nerdfishui
Esc
navigateopen⌘Jpreview
On this page

Message

Lay out a single message in a conversation with avatar, alignment, header, and footer slots.

'use client'

import { Avatar, AvatarFallback, AvatarImage } from '@nerdfish/react/avatar'
import { Bubble, BubbleContent } from '@nerdfish/react/bubble'
import { Marker, MarkerContent } from '@nerdfish/react/marker'
import {
	Message,
	MessageAvatar,
	MessageContent,
	MessageFooter,
} from '@nerdfish/react/message'

export default function MessageExample() {
	return (
		<div className="gap-casual py-casual mx-auto flex w-full max-w-sm flex-col">
			<Message align="end">
				<MessageAvatar>
					<Avatar className="size-8">
						<AvatarImage
							src="https://avatars.githubusercontent.com/u/56068461?v=4"
							alt="@me"
						/>
						<AvatarFallback>ME</AvatarFallback>
					</Avatar>
				</MessageAvatar>
				<MessageContent>
					<Bubble>
						<BubbleContent>Deploying to prod real quick.</BubbleContent>
					</Bubble>
				</MessageContent>
			</Message>
			<Message>
				<MessageAvatar>
					<Avatar className="size-8">
						<AvatarImage
							src="https://randomuser.me/api/portraits/men/32.jpg"
							alt="@rabbit"
						/>
						<AvatarFallback>R</AvatarFallback>
					</Avatar>
				</MessageAvatar>
				<MessageContent>
					<Bubble variant="muted">
						<BubbleContent>It&apos;s 4:55 PM. On a Friday.</BubbleContent>
					</Bubble>
				</MessageContent>
			</Message>
			<Message align="end">
				<MessageAvatar>
					<Avatar className="size-8">
						<AvatarImage
							src="https://avatars.githubusercontent.com/u/56068461?v=4"
							alt="@me"
						/>
						<AvatarFallback>ME</AvatarFallback>
					</Avatar>
				</MessageAvatar>
				<MessageContent>
					<Bubble>
						<BubbleContent>It&apos;s a one-line change.</BubbleContent>
					</Bubble>
					<MessageFooter>Delivered</MessageFooter>
				</MessageContent>
			</Message>
			<Message>
				<MessageAvatar>
					<Avatar className="size-8">
						<AvatarImage
							src="https://randomuser.me/api/portraits/men/32.jpg"
							alt="@rabbit"
						/>
						<AvatarFallback>R</AvatarFallback>
					</Avatar>
				</MessageAvatar>
				<MessageContent>
					<Bubble variant="muted">
						<BubbleContent>It&apos;s always a one-line change.</BubbleContent>
					</Bubble>
					<Bubble variant="muted">
						<BubbleContent>Alright, let me take a look.</BubbleContent>
					</Bubble>
				</MessageContent>
			</Message>
			<Marker role="status">
				<MarkerContent className="shimmer">
					<span className="font-medium">Oliver</span> is typing...
				</MarkerContent>
			</Marker>
		</div>
	)
}

Usage

<Message>
	<MessageAvatar>
		<Avatar>
			<AvatarImage
				src="https://avatars.githubusercontent.com/u/56068461?v=4"
				alt="@nerdfish"
			/>
			<AvatarFallback>NF</AvatarFallback>
		</Avatar>
	</MessageAvatar>
	<MessageContent>
		<Bubble>
			<BubbleContent>How can I help you today?</BubbleContent>
		</Bubble>
	</MessageContent>
</Message>

Message owns the row layout — avatar, alignment, header, and footer. Render the visible message surface inside it with Bubble.

Group

Use MessageGroup to stack consecutive messages from the same sender. Render an empty MessageAvatar on earlier messages to keep alignment with the avatar on the last one.

'use client'

import { Avatar, AvatarFallback, AvatarImage } from '@nerdfish/react/avatar'
import { Bubble, BubbleContent } from '@nerdfish/react/bubble'
import {
	Message,
	MessageAvatar,
	MessageContent,
	MessageGroup,
} from '@nerdfish/react/message'

export default function MessageGroupExample() {
	return (
		<div className="py-casual mx-auto flex w-full max-w-sm flex-col">
			<MessageGroup>
				<Message>
					<MessageAvatar />
					<MessageContent>
						<Bubble variant="muted">
							<BubbleContent>I checked the registry addresses.</BubbleContent>
						</Bubble>
					</MessageContent>
				</Message>
				<Message>
					<MessageAvatar>
						<Avatar className="size-8">
							<AvatarImage
								src="https://randomuser.me/api/portraits/men/32.jpg"
								alt="@rabbit"
							/>
							<AvatarFallback>R</AvatarFallback>
						</Avatar>
					</MessageAvatar>
					<MessageContent>
						<Bubble variant="muted">
							<BubbleContent>
								The component and example JSON now live under the UI registry.
							</BubbleContent>
						</Bubble>
					</MessageContent>
				</Message>
			</MessageGroup>
		</div>
	)
}

Use MessageHeader for a sender name and MessageFooter for metadata such as delivery or read status.

'use client'

import { Bubble, BubbleContent } from '@nerdfish/react/bubble'
import {
	Message,
	MessageContent,
	MessageFooter,
	MessageHeader,
} from '@nerdfish/react/message'

export default function MessageHeaderFooterExample() {
	return (
		<div className="gap-casual py-casual mx-auto flex w-full max-w-sm flex-col">
			<Message>
				<MessageContent>
					<MessageHeader>Olivia</MessageHeader>
					<Bubble variant="muted">
						<BubbleContent>I already checked the logs.</BubbleContent>
					</Bubble>
				</MessageContent>
			</Message>
			<Message align="end">
				<MessageContent>
					<Bubble>
						<BubbleContent>
							Send the report to the team. Ping @nerdfish if you need help.
						</BubbleContent>
					</Bubble>
					<MessageFooter>
						Read <span className="font-normal">Yesterday</span>
					</MessageFooter>
				</MessageContent>
			</Message>
		</div>
	)
}