MemPrepMate / src /lib /components /ChatMessage.svelte
Christian Kniep
new webapp
1fff71f
<script lang="ts">
import type { Message } from '$lib/types/api';
import { formatDateTime, formatTime } from '$lib/utils/formatters';
export let message: Message;
export let isUser = false; // true for user messages, false for assistant messages
function getModeColor(mode: string): string {
switch (mode) {
case 'chat':
return 'primary';
case 'memorize':
return 'success';
case 'parse':
return 'info';
default:
return 'secondary';
}
}
function getModeIcon(mode: string): string {
switch (mode) {
case 'chat':
return 'bi-chat-left-text';
case 'memorize':
return 'bi-journal-bookmark';
case 'parse':
return 'bi-code-slash';
default:
return 'bi-chat-dots';
}
}
</script>
<div class="chat-message mb-3" class:user-message={isUser} class:assistant-message={!isUser}>
<div class="message-container" class:ms-auto={isUser}>
<div class="message-header d-flex justify-content-between align-items-center mb-1">
<span class="badge bg-{getModeColor(message.mode)}">
<i class="{getModeIcon(message.mode)} me-1"></i>
{message.mode}
</span>
<small class="text-muted ms-2" title={formatDateTime(message.created_at)}>
{formatTime(message.created_at)}
</small>
</div>
<div class="message-content">
{message.content}
</div>
</div>
</div>
<style>
.chat-message {
display: flex;
width: 100%;
}
.message-container {
max-width: 70%;
padding: 0.75rem 1rem;
border-radius: 1rem;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
/* User messages - right-aligned, blue background */
.user-message .message-container {
background-color: #0d6efd;
color: white;
border-bottom-right-radius: 0.25rem;
}
.user-message .message-header .badge {
background-color: rgba(255, 255, 255, 0.2) !important;
color: white;
}
.user-message .message-header .text-muted {
color: rgba(255, 255, 255, 0.8) !important;
}
/* Assistant messages - left-aligned, gray background */
.assistant-message {
justify-content: flex-start;
}
.assistant-message .message-container {
background-color: #f8f9fa;
color: #212529;
border-bottom-left-radius: 0.25rem;
}
.message-content {
white-space: pre-wrap;
word-break: break-word;
line-height: 1.5;
font-size: 0.95rem;
}
.message-header {
font-size: 0.875rem;
}
/* Responsive breakpoints */
@media (max-width: 576px) {
.message-container {
max-width: 90%;
padding: 0.625rem 0.875rem;
}
.message-content {
font-size: 0.9rem;
}
.message-header {
font-size: 0.8125rem;
}
.badge {
font-size: 0.75rem;
}
}
@media (min-width: 577px) and (max-width: 768px) {
.message-container {
max-width: 85%;
}
}
@media (min-width: 769px) and (max-width: 992px) {
.message-container {
max-width: 75%;
}
}
@media (min-width: 1200px) {
.message-container {
max-width: 65%;
}
}
</style>