← All proposals

Chat Message

ChatMessage, with sender: user or agent.

Net-new componentOpen in Storybook

proposals/ChatMessage/ChatMessage.tsx61 lines · View on GitHub
import { ComponentPropsWithoutRef, ReactNode } from 'react';

import './chat-message.css';

export type ChatMessageSender = 'agent' | 'user';

export interface ChatMessageProps extends ComponentPropsWithoutRef<'div'> {
	/**
	 * The message content. Text for a user message; anything for an agent
	 * message (text, lists, a Thinking State, Chain of Thought).
	 */
	children: ReactNode;
	/**
	 * Additional class names.
	 */
	className?: string;
	/**
	 * Who sent it, read by screen readers before the message (for example "You"
	 * or "Zappy"). Visually hidden.
	 */
	label: string;
	/**
	 * Who the message is from. `user` is a bubble on the right that hugs its
	 * content. `agent` is plain content across the full width.
	 */
	sender?: ChatMessageSender;
}

// Stand-in for the v2 `mergeClasses` util, which the published package does
// not export. The port uses the real one.
const mergeClasses = (classes: Array<string | null | undefined>) =>
	classes.filter(Boolean).join(' ');

/**
 * ChatMessage UI component. One turn in a conversation, from the user or from
 * an agent.
 */
export const ChatMessage = ({
	children,
	className,
	label,
	sender = 'agent',
	...props
}: ChatMessageProps) => {
	const baseClass = 'pds-chat-message';

	return (
		<div
			className={mergeClasses([
				baseClass,
				`${baseClass}--${sender}`,
				className,
			])}
			{...props}
		>
			<span className='visually-hidden'>{label}</span>
			<div className={`${baseClass}__content`}>{children}</div>
		</div>
	);
};