From 54ee2f3b0034f0b598ec0ec9ff1b846b9f590acd Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:56:22 +0800 Subject: [PATCH] feat(ui): add streaming indicator to StreamingMarkdown Show a spinner with "Generating..." label while assistant messages are being streamed. The indicator appears immediately when content is empty and persists below the content until streaming completes. Also fix duplicate React key warning by including block index in the key to handle blocks with identical content. Co-Authored-By: Claude Opus 4.5 --- .../src/components/markdown/StreamingMarkdown.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/components/markdown/StreamingMarkdown.tsx b/packages/ui/src/components/markdown/StreamingMarkdown.tsx index 6d68435f..65b585a8 100644 --- a/packages/ui/src/components/markdown/StreamingMarkdown.tsx +++ b/packages/ui/src/components/markdown/StreamingMarkdown.tsx @@ -1,5 +1,6 @@ import * as React from 'react' import { Markdown, type RenderMode } from './Markdown' +import { Spinner } from '@multica/ui/components/spinner' export interface StreamingMarkdownProps { content: string @@ -162,6 +163,17 @@ export function StreamingMarkdown({ ) } + const indicator = ( +
+ + Generating... +
+ ) + + if (blocks.length === 0) { + return indicator + } + return ( <> {blocks.map((block, i) => { @@ -169,7 +181,7 @@ export function StreamingMarkdown({ // Complete blocks use content hash as key -> stable identity -> memoized // Last block uses "active" prefix -> always re-renders on content change - const key = isLastBlock ? `active-${i}` : `block-${simpleHash(block.content)}` + const key = isLastBlock ? `active-${i}` : `block-${i}-${simpleHash(block.content)}` return ( ) })} + {indicator} ) }