Replace the full-bleed cyan/violet/emerald bloom field with one dark glass panel: the Oo, a live caption whose new words fade in, and a compact control row (phase label, transcript, interrupt, hang up). An iridescent aurora rises from the panel's bottom edge, follows mic energy while listening, drifts while thinking and blooms while speaking. Its spectrum is the shared bot palette rotated so the active Oo's color sits in the middle, so no new hex values. Voice entry buttons drop the hardcoded cyan/amber styling for neutral tokens plus a thin aurora rim when voice is ready. Dead voice CSS is removed and the voice e2e now captures the stage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012G3dUMVDCDL3PwQE4WTQxL
31 lines
962 B
TypeScript
31 lines
962 B
TypeScript
import { useRef } from "react";
|
|
import { captionWords, continuesCaption } from "../../lib/voice-aurora";
|
|
|
|
/** Live caption whose new words fade in as they are heard or spoken. */
|
|
export function VoiceLiveText({ text, reducedMotion }: { text: string; reducedMotion: boolean }) {
|
|
const shown = useRef({ text: "", utterance: 0 });
|
|
if (shown.current.text !== text) {
|
|
shown.current = {
|
|
text,
|
|
utterance: continuesCaption(shown.current.text, text)
|
|
? shown.current.utterance
|
|
: shown.current.utterance + 1,
|
|
};
|
|
}
|
|
const { utterance } = shown.current;
|
|
|
|
return (
|
|
<p
|
|
dir="auto"
|
|
className="text-balance text-center text-ui-title font-medium leading-snug text-foreground"
|
|
>
|
|
{captionWords(text).map((word, index) => (
|
|
<span key={`${utterance}-${index}`} className={reducedMotion ? undefined : "voice-word-in"}>
|
|
{index ? " " : ""}
|
|
{word}
|
|
</span>
|
|
))}
|
|
</p>
|
|
);
|
|
}
|