show-me / src /components /Transcript.svelte
PierreRouanet's picture
V1: Add voice interaction with STT/TTS and keyword commands
aaf834a
Raw
History Blame Contribute Delete
1.62 kB
<script>
/** @type {{ history: Array<{ role: string, text: string }> }} */
let { history } = $props();
// Show only last 5 messages
let visible = $derived(history.slice(-5));
let container = $state(null);
// Auto-scroll when new messages arrive
$effect(() => {
if (container && visible.length) {
container.scrollTop = container.scrollHeight;
}
});
</script>
{#if visible.length > 0}
<div class="transcript" bind:this={container}>
{#each visible as msg, i (history.length - visible.length + i)}
<div class="bubble {msg.role}">
<span class="text">{msg.text}</span>
</div>
{/each}
</div>
{/if}
<style>
.transcript {
position: absolute;
top: 48px;
left: 16px;
right: 16px;
max-height: 40%;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 8px;
pointer-events: none;
z-index: 10;
scrollbar-width: none;
}
.transcript::-webkit-scrollbar {
display: none;
}
.bubble {
max-width: 80%;
padding: 8px 14px;
border-radius: 16px;
font-size: 0.85rem;
line-height: 1.4;
backdrop-filter: blur(8px);
animation: fadeIn 0.3s ease-out;
}
.bubble.user {
align-self: flex-end;
background: rgba(59, 130, 246, 0.6);
color: #fff;
border-bottom-right-radius: 4px;
}
.bubble.assistant {
align-self: flex-start;
background: rgba(255, 255, 255, 0.15);
color: #fff;
border-bottom-left-radius: 4px;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
</style>