Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | 'use client';
/**
* ChatMessage - Individual message bubble in the chat
*/
import React from 'react';
import { ChatbotMessage, ChatbotQuickAction, SupportArticle } from '@/types/support';
export interface ChatMessageProps {
/** The message to display */
message: ChatbotMessage;
/** Handler for quick action clicks */
onQuickAction?: (action: ChatbotQuickAction) => void;
/** Handler for article clicks */
onArticleClick?: (article: SupportArticle) => void;
}
export default function ChatMessage({
message,
onQuickAction,
onArticleClick}: ChatMessageProps) {
const isBot = message.type === 'bot';
return (
<div className={`flex ${isBot ? 'justify-start' : 'justify-end'}`}>
<div
className={`
max-w-[85%] rounded-lg px-4 py-2
${
isBot
? 'bg-white text-gray-800 shadow-sm border border-gray-100'
: 'bg-blue-600 text-white'
}
`}
>
{/* Message content */}
<p className="text-sm whitespace-pre-wrap">{message.content}</p>
{/* Suggested articles */}
{isBot && message.suggestedArticles && message.suggestedArticles.length > 0 && (
<div className="mt-3 space-y-2">
<p className="text-xs text-gray-500 font-medium">Suggested articles:</p>
{message.suggestedArticles.map((article) => (
<button
key={article.id}
type="button"
onClick={() => onArticleClick?.(article)}
className="
block w-full text-left p-2 rounded
bg-gray-50 hover:bg-gray-100
border border-gray-200
transition-colors
"
>
<p className="text-sm font-medium text-blue-600 hover:text-blue-700">
{article.title}
</p>
<p className="text-xs text-gray-500 line-clamp-2">{article.summary}</p>
</button>
))}
</div>
)}
{/* Quick actions within message */}
{isBot && message.quickActions && message.quickActions.length > 0 && (
<div className="mt-3 flex flex-wrap gap-2">
{message.quickActions.map((action, index) => (
<button
key={index}
type="button"
onClick={() => onQuickAction?.(action)}
className="
px-3 py-1.5 text-xs font-medium
bg-blue-50 text-blue-600
rounded-full
hover:bg-blue-100
transition-colors
"
>
{action.label}
</button>
))}
</div>
)}
{/* Timestamp */}
<p
className={`
text-[10px] mt-1
${isBot ? 'text-gray-400' : 'text-blue-200'}
`}
>
{new Date(message.timestamp).toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit'})}
</p>
</div>
</div>
);
}
|