Files
klz-cables.com/components/blog/ChatBubble.tsx
2026-01-19 02:05:30 +01:00

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>
);
}