66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import React from 'react';
|
|
import Image from 'next/image';
|
|
|
|
interface ChatBubbleProps {
|
|
author?: string;
|
|
avatar?: string;
|
|
role?: string;
|
|
children: React.ReactNode;
|
|
align?: 'left' | 'right';
|
|
}
|
|
|
|
export default function ChatBubble({
|
|
author = 'KLZ Team',
|
|
avatar = '/uploads/2024/11/cropped-favicon-3-192x192.png', // Default fallback
|
|
role = 'Assistant',
|
|
children,
|
|
align = 'left',
|
|
}: ChatBubbleProps) {
|
|
const isRight = align === 'right';
|
|
|
|
return (
|
|
<div className={`flex w-full gap-4 my-10 ${isRight ? 'flex-row-reverse' : 'flex-row'}`}>
|
|
{/* Avatar */}
|
|
<div className="flex-shrink-0 flex flex-col items-center gap-1">
|
|
<div className="w-10 h-10 rounded-full overflow-hidden border border-neutral-200 shadow-sm relative">
|
|
{/* Use a simple div placeholder if image fails or isn't provided, but here we assume a path */}
|
|
<div className="w-full h-full bg-neutral-100 flex items-center justify-center text-xs font-bold text-neutral-400">
|
|
{author.charAt(0)}
|
|
</div>
|
|
{avatar && (
|
|
<Image
|
|
src={avatar}
|
|
alt={author}
|
|
fill
|
|
className="object-cover"
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Message Bubble */}
|
|
<div className={`flex flex-col max-w-[85%] ${isRight ? 'items-end' : 'items-start'}`}>
|
|
<div className="flex items-baseline gap-2 mb-1">
|
|
<span className="text-sm font-bold text-text-primary">{author}</span>
|
|
{role && <span className="text-xs text-text-secondary">{role}</span>}
|
|
</div>
|
|
|
|
<div className={`
|
|
relative px-8 py-6 rounded-3xl shadow-sm border transition-all duration-300 hover:shadow-md
|
|
${isRight
|
|
? 'bg-neutral-dark text-white rounded-tr-none border-neutral-dark'
|
|
: 'bg-white text-text-primary rounded-tl-none border-neutral-200'
|
|
}
|
|
`}>
|
|
<div className={`prose prose-lg max-w-none ${isRight ? 'prose-invert' : ''}`}>
|
|
{children}
|
|
</div>
|
|
|
|
{/* Industrial accent dot */}
|
|
<div className={`absolute top-4 ${isRight ? 'left-4' : 'right-4'} w-1.5 h-1.5 rounded-full ${isRight ? 'bg-primary' : 'bg-primary/30'}`} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|