Skip to content

Commit 0a91ab9

Browse files
committed
improvement(ui): delegate streaming animation to Streamdown component
Remove custom useStreamingText hook and useThrottledValue indirection in favor of Streamdown's built-in streaming props. This eliminates the manual character-by-character reveal logic (setInterval, easing, chase factor) and lets the library handle animation natively, reducing complexity and improving consistency across Mothership and chat.
1 parent 64cdab2 commit 0a91ab9

File tree

5 files changed

+22
-115
lines changed

5 files changed

+22
-115
lines changed

apps/sim/app/chat/components/message/components/markdown-renderer.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,11 @@ const DEFAULT_COMPONENTS = createCustomComponents(LinkWithPreview)
176176
const MarkdownRenderer = memo(function MarkdownRenderer({
177177
content,
178178
customLinkComponent,
179+
isStreaming = false,
179180
}: {
180181
content: string
181182
customLinkComponent?: typeof LinkWithPreview
183+
isStreaming?: boolean
182184
}) {
183185
const components = useMemo(() => {
184186
if (!customLinkComponent) {
@@ -191,7 +193,12 @@ const MarkdownRenderer = memo(function MarkdownRenderer({
191193

192194
return (
193195
<div className='space-y-4 break-words font-sans text-[var(--landing-text)] text-base leading-relaxed'>
194-
<Streamdown mode='static' components={components}>
196+
<Streamdown
197+
mode={isStreaming ? undefined : 'static'}
198+
isAnimating={isStreaming}
199+
animated={isStreaming}
200+
components={components}
201+
>
195202
{processedContent}
196203
</Streamdown>
197204
</div>

apps/sim/app/chat/components/message/message.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
ChatFileDownloadAll,
99
} from '@/app/chat/components/message/components/file-download'
1010
import MarkdownRenderer from '@/app/chat/components/message/components/markdown-renderer'
11-
import { useThrottledValue } from '@/hooks/use-throttled-value'
1211

1312
export interface ChatAttachment {
1413
id: string
@@ -39,9 +38,14 @@ export interface ChatMessage {
3938
files?: ChatFile[]
4039
}
4140

42-
function EnhancedMarkdownRenderer({ content }: { content: string }) {
43-
const throttled = useThrottledValue(content)
44-
return <MarkdownRenderer content={throttled} />
41+
function EnhancedMarkdownRenderer({
42+
content,
43+
isStreaming,
44+
}: {
45+
content: string
46+
isStreaming?: boolean
47+
}) {
48+
return <MarkdownRenderer content={content} isStreaming={isStreaming} />
4549
}
4650

4751
export const ClientChatMessage = memo(
@@ -188,7 +192,10 @@ export const ClientChatMessage = memo(
188192
{JSON.stringify(cleanTextContent, null, 2)}
189193
</pre>
190194
) : (
191-
<EnhancedMarkdownRenderer content={cleanTextContent as string} />
195+
<EnhancedMarkdownRenderer
196+
content={cleanTextContent as string}
197+
isStreaming={message.isStreaming}
198+
/>
192199
)}
193200
</div>
194201
</div>

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
SpecialTags,
1919
} from '@/app/workspace/[workspaceId]/home/components/message-content/components/special-tags'
2020
import type { MothershipResource } from '@/app/workspace/[workspaceId]/home/types'
21-
import { useStreamingText } from '@/hooks/use-streaming-text'
2221

2322
const LANG_ALIASES: Record<string, string> = {
2423
js: 'javascript',
@@ -236,15 +235,13 @@ interface ChatContentProps {
236235
isStreaming?: boolean
237236
onOptionSelect?: (id: string) => void
238237
onWorkspaceResourceSelect?: (resource: MothershipResource) => void
239-
smoothStreaming?: boolean
240238
}
241239

242240
export function ChatContent({
243241
content,
244242
isStreaming = false,
245243
onOptionSelect,
246244
onWorkspaceResourceSelect,
247-
smoothStreaming = true,
248245
}: ChatContentProps) {
249246
const hydratedStreamingRef = useRef(isStreaming && content.trim().length > 0)
250247
const previousIsStreamingRef = useRef(isStreaming)
@@ -270,9 +267,7 @@ export function ChatContent({
270267
return () => window.removeEventListener('wsres-click', handler)
271268
}, [])
272269

273-
const rendered = useStreamingText(content, isStreaming && smoothStreaming)
274-
275-
const parsed = useMemo(() => parseSpecialTags(rendered, isStreaming), [rendered, isStreaming])
270+
const parsed = useMemo(() => parseSpecialTags(content, isStreaming), [content, isStreaming])
276271
const hasSpecialContent = parsed.hasPendingTag || parsed.segments.some((s) => s.type !== 'text')
277272

278273
if (hasSpecialContent) {
@@ -349,7 +344,7 @@ export function ChatContent({
349344
animated={isStreaming && !hydratedStreamingRef.current}
350345
components={MARKDOWN_COMPONENTS}
351346
>
352-
{rendered}
347+
{content}
353348
</Streamdown>
354349
</div>
355350
)

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,6 @@ export function MessageContent({
374374
const hasSubagentEnded = blocks.some((b) => b.type === 'subagent_end')
375375
const showTrailingThinking =
376376
isStreaming && !hasTrailingContent && (hasSubagentEnded || allLastGroupToolsDone)
377-
const hasStructuredSegments = segments.some((segment) => segment.type !== 'text')
378377
const lastOpenSubagentGroupId = [...segments]
379378
.reverse()
380379
.find(
@@ -394,7 +393,6 @@ export function MessageContent({
394393
isStreaming={isStreaming}
395394
onOptionSelect={onOptionSelect}
396395
onWorkspaceResourceSelect={onWorkspaceResourceSelect}
397-
smoothStreaming={!hasStructuredSegments}
398396
/>
399397
)
400398
case 'agent_group': {

apps/sim/hooks/use-streaming-text.ts

Lines changed: 0 additions & 100 deletions
This file was deleted.

0 commit comments

Comments
 (0)