"use client"; import { Reasoning, ReasoningContent, ReasoningTrigger, } from "@/components/ai-elements/reasoning"; import { useCallback, useEffect, useState } from "react"; const reasoningSteps = [ "Let me think about this problem step by step.", "\n\nFirst, I need to understand what the user is asking for.", "\n\nThey want a reasoning component that opens automatically when streaming begins and closes when streaming finishes. The component should be composable and follow existing patterns in the codebase.", "\n\nThis seems like a collapsible component with state management would be the right approach.", ].join(""); const Example = () => { const [content, setContent] = useState(""); const [isStreaming, setIsStreaming] = useState(false); const [currentTokenIndex, setCurrentTokenIndex] = useState(0); const [tokens, setTokens] = useState([]); // Function to chunk text into fake tokens of 3-4 characters const chunkIntoTokens = useCallback((text: string): string[] => { const chunks: string[] = []; let i = 0; while (i < text.length) { // Random size between 3-4 const chunkSize = Math.floor(Math.random() * 2) + 3; chunks.push(text.slice(i, i + chunkSize)); i += chunkSize; } return chunks; }, []); useEffect(() => { const tokenizedSteps = chunkIntoTokens(reasoningSteps); setTokens(tokenizedSteps); setContent(""); setCurrentTokenIndex(0); setIsStreaming(true); }, [chunkIntoTokens]); useEffect(() => { if (!isStreaming || currentTokenIndex >= tokens.length) { if (isStreaming) { setIsStreaming(false); } return; } // Faster interval since we're streaming smaller chunks const timer = setTimeout(() => { setContent((prev) => prev + tokens[currentTokenIndex]); setCurrentTokenIndex((prev) => prev + 1); }, 25); return () => clearTimeout(timer); }, [isStreaming, currentTokenIndex, tokens]); return (
{content}
); }; export default Example;