From f5a6c8d92ce76b12418b307b1223bc36e66f80eb Mon Sep 17 00:00:00 2001 From: Xiaohan-Tian <157918347+Xiaohan-Tian@users.noreply.github.com> Date: Fri, 15 Aug 2025 19:34:13 -0700 Subject: [PATCH] added a subtle wave animation to the 'processing...' text. --- src/App.css | 26 +++++++++++ src/components/ChatBox.tsx | 8 ++-- src/components/chat/AssistantMessage.tsx | 57 ++++++++++++++++++------ 3 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/App.css b/src/App.css index 32c534c..c64ba48 100644 --- a/src/App.css +++ b/src/App.css @@ -1964,3 +1964,29 @@ textarea { @keyframes globalSpinner { to { transform: rotate(360deg); } } + +/* Processing wave animation */ +.processing-wave { + background: linear-gradient( + 90deg, + rgba(135, 206, 250, 0.5) 0%, + rgba(135, 206, 250, 0.8) 25%, + rgb(171, 218, 250) 50%, + rgba(135, 206, 250, 0.8) 75%, + rgba(135, 206, 250, 0.5) 100% + ); + background-size: 200% 100%; + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + animation: wave 2s linear infinite; +} + +@keyframes wave { + 0% { + background-position: 200% 0%; + } + 100% { + background-position: -200% 0%; + } +} diff --git a/src/components/ChatBox.tsx b/src/components/ChatBox.tsx index 9734855..e6a0c97 100644 --- a/src/components/ChatBox.tsx +++ b/src/components/ChatBox.tsx @@ -276,7 +276,7 @@ const ChatBox: React.FC = ({ isVisible }) => { setMessages(prev => [...prev, { id: assistantMsgId, role: 'assistant', - content: 'processing... 0 tokens received. click here to abort.', + content: 'Processing... 0 tokens received. click here to abort.', isStreaming: true, tokenCount: 0 }]); @@ -304,7 +304,7 @@ const ChatBox: React.FC = ({ isVisible }) => { // Update streaming message with token count and abort link setMessages(prev => prev.map(msg => msg.id === assistantMsgId - ? { ...msg, content: `processing... ${tokenCount} tokens received. click here to abort.`, tokenCount } + ? { ...msg, content: `Processing... ${tokenCount} tokens received. click here to abort.`, tokenCount } : msg )); } else if (chunk.type === 'done') { @@ -396,7 +396,7 @@ const ChatBox: React.FC = ({ isVisible }) => { setMessages(prev => [...prev, { id: assistantMsgId, role: 'assistant', - content: 'processing... 0 tokens received. click here to abort.', + content: 'Processing... 0 tokens received. click here to abort.', isStreaming: true, tokenCount: 0 }]); @@ -441,7 +441,7 @@ const ChatBox: React.FC = ({ isVisible }) => { // Update streaming message with token count and abort link setMessages(prev => prev.map(msg => msg.id === assistantMsgId - ? { ...msg, content: `processing... ${tokenCount} tokens received. click here to abort.`, tokenCount } + ? { ...msg, content: `Processing... ${tokenCount} tokens received. click here to abort.`, tokenCount } : msg )); } else if (chunk.type === 'done') { diff --git a/src/components/chat/AssistantMessage.tsx b/src/components/chat/AssistantMessage.tsx index a7670b1..ff5f91f 100644 --- a/src/components/chat/AssistantMessage.tsx +++ b/src/components/chat/AssistantMessage.tsx @@ -113,19 +113,50 @@ const AssistantMessage: React.FC = ({ content, isStreamin // Handle special abort link for streaming messages const renderContent = () => { if (isStreaming && onAbort && content.includes('click here to abort')) { - const parts = content.split('click here to abort'); - return ( - - {parts[0]} - - {parts[1]} - - ); + // Check if content has the processing wave HTML + const hasProcessingWave = content.includes('Processing...'); + + if (hasProcessingWave) { + // Parse the content to handle both the wave animation and abort link + const parts = content.split('click here to abort'); + const beforeAbort = parts[0]; + const afterAbort = parts[1]; + + // Replace the HTML span with JSX + const processedBefore = beforeAbort.replace( + 'Processing...', + '' + ); + + return ( + + Processing... + {processedBefore} + + {afterAbort} + + ); + } else { + // Original logic for non-wave processing messages + const parts = content.split('click here to abort'); + return ( + + {parts[0]} + + {parts[1]} + + ); + } } const processedContent = processContentWithXMLExpanders(content);