optimized webchat

This commit is contained in:
2025-10-05 17:00:46 +00:00
parent 8ae3c914d8
commit 740cb3e1e6
6 changed files with 397 additions and 74 deletions

View File

@@ -1,23 +1,141 @@
<script lang="ts">
import type { WerkChatSession } from "@kontextwerk/web-sdk"
import type { ChatMessage } from "@kontextwerk/web-sdk"
let {
chat,
messages = [],
streaming,
}: {
chat: WerkChatSession
messages?: ChatMessage[]
streaming: boolean
} = $props()
</script>
<div>
{#each chat.messages as message, idx (idx)}
<div
class="message"
class:assistant={message.role === "assistant"}
class:user={message.role === "user"}
>
{@html message.content}
</div>
<div class="messages">
{#each messages as message, idx (idx)}
{#if message.role === "assistant"}
<div class="message assistant">
<div class="bubble assistant-bubble">
{@html message.content || ""}
</div>
</div>
{:else if message.role === "user"}
<div class="message user">
<div class="bubble user-bubble">
{@html message.content}
</div>
</div>
{:else}
<div class="message system">
<div class="bubble system-bubble">
{@html message.content}
</div>
</div>
{/if}
{/each}
{#if streaming}
<div class="message assistant typing-indicator">
<div class="bubble assistant-bubble">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</div>
{/if}
</div>
<style lang="less">
.messages {
display: flex;
flex-direction: column;
gap: 0.9rem;
padding: 1rem 0;
color: var(--text-reverse-100);
}
.message {
display: flex;
flex-direction: column;
max-width: 85%;
&.assistant {
align-self: flex-start;
}
&.user {
align-self: flex-end;
}
&.system {
align-self: center;
}
}
.bubble {
padding: 0.85rem 1.05rem;
border-radius: 1.1rem;
line-height: 1.45;
font-size: 0.95rem;
box-shadow: 0 0.8rem 2rem rgba(0, 0, 0, 0.08);
position: relative;
overflow-wrap: anywhere;
background: white;
&.assistant-bubble {
background: white;
color: var(--text-reverse-100);
border: 1px solid rgba(0, 0, 0, 0.04);
}
&.user-bubble {
background: linear-gradient(135deg, var(--primary-100), var(--primary-200));
color: white;
}
&.system-bubble {
background: rgba(255, 255, 255, 0.6);
color: var(--text-reverse-100);
font-style: italic;
}
}
.typing-indicator .bubble {
display: inline-flex;
align-items: center;
gap: 0.35rem;
}
.typing-indicator .dot {
height: 8px;
width: 8px;
background-color: rgba(0, 0, 0, 0.25);
border-radius: 50%;
display: inline-block;
animation: typingAnimation 1.4s infinite both;
}
.typing-indicator .dot:nth-child(2) {
animation-delay: 0.2s;
}
.typing-indicator .dot:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes typingAnimation {
0%,
80%,
100% {
opacity: 0.3;
transform: translateY(0);
}
40% {
opacity: 1;
transform: translateY(-4px);
}
}
@media (max-width: 768px) {
.message {
max-width: 92%;
}
}
</style>