From c54158b682448305d74b70870bf3a8098a20fbf7 Mon Sep 17 00:00:00 2001 From: Dexter Storey <36115192+DexterStorey@users.noreply.github.com> Date: Thu, 25 Dec 2025 21:44:57 -0500 Subject: [PATCH 1/2] Improve chat ordering and polish UI --- src/app/(app)/ToggleRealtime.tsx | 42 ++++++++++++++++++-------------- src/realtime/provider.tsx | 9 +++++-- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/app/(app)/ToggleRealtime.tsx b/src/app/(app)/ToggleRealtime.tsx index 2bce097..f713243 100644 --- a/src/app/(app)/ToggleRealtime.tsx +++ b/src/app/(app)/ToggleRealtime.tsx @@ -1,7 +1,15 @@ 'use client' import { AnimatePresence, motion } from 'framer-motion' -import { type CSSProperties, useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { + type CSSProperties, + useCallback, + useEffect, + useLayoutEffect, + useMemo, + useRef, + useState +} from 'react' import { useRealtimeVoiceSession } from '@/realtime/provider' @@ -357,7 +365,6 @@ export default function ToggleRealtime() { const [activeIndex, setActiveIndex] = useState(0) const transcriptListRef = useRef(null) - const transcriptBottomRef = useRef(null) const stickToBottomRef = useRef(true) useEffect(() => { @@ -373,6 +380,7 @@ export default function ToggleRealtime() { const phrase = languageOrder[activeIndex] ?? languageOrder[0] const footerText = tab === 'session' ? statusText : '' const canSendText = textDraft.trim().length > 0 + const transcriptCount = transcripts.length useEffect(() => { const el = transcriptListRef.current @@ -390,36 +398,36 @@ export default function ToggleRealtime() { } }, []) - useEffect(() => { - if (!stickToBottomRef.current) return - // Trigger on streaming updates (deltas) while the user is pinned to the bottom. - void transcripts - transcriptBottomRef.current?.scrollIntoView({ behavior: 'auto' }) - }, [transcripts]) + useLayoutEffect(() => { + const el = transcriptListRef.current + if (!el || !stickToBottomRef.current || transcriptCount === 0) return + el.scrollTop = el.scrollHeight + }, [transcriptCount]) const content = tab === 'session' ? (
{transcripts.length ? ( -
+
{transcripts.map(item => { const isUser = item.role === 'user' const bubbleBase = - 'max-w-[92%] whitespace-pre-wrap rounded-3xl px-4 py-3 text-sm leading-relaxed shadow-sm' + 'max-w-[90%] whitespace-pre-wrap rounded-[22px] px-4 py-3 text-sm leading-relaxed shadow-md' const bubbleClass = isUser - ? `${bubbleBase} self-end bg-[var(--lilac-ink)] text-[var(--lilac-surface)]` - : `${bubbleBase} self-start border border-white/30 bg-white/70 text-[var(--lilac-ink)] dark:border-white/22 dark:bg-white/14 dark:text-[var(--lilac-ink)]` + ? `${bubbleBase} self-end bg-[linear-gradient(135deg,rgba(53,32,73,0.95),rgba(80,52,110,0.92))] text-[var(--lilac-surface)]` + : `${bubbleBase} self-start border border-white/30 bg-white/70 text-[var(--lilac-ink)] dark:border-white/22 dark:bg-white/12 dark:text-[var(--lilac-ink)]` const label = isUser ? 'You' : 'Lilac' const text = item.text?.trim() ? item.text : '…' return (
@@ -430,7 +438,6 @@ export default function ToggleRealtime() {
) })} -
) : (
@@ -449,14 +456,13 @@ export default function ToggleRealtime() {

Your spoken conversation will appear here as a live transcript.

-
)}
-
+