Docs
🪄 ⏐ Examples
Message Status

Message Status

reachat 2.1 introduces the MessageStatus component for displaying loading, complete, and error states with optional multi-step progress indicators, similar to Claude's tool status UI.

Overview

The MessageStatus component provides:

  • Visual status indicators (loading, complete, error)
  • Animated state transitions
  • Multi-step progress display
  • Customizable icons
  • Support for nested status steps

Basic Usage

Display a simple status message:

import { MessageStatus } from 'reachat';
 
<MessageStatus
  status="loading"
  text="Processing your request..."
/>

Status States

The component supports three status states:

Loading State

<MessageStatus
  status="loading"
  text="Analyzing data..."
/>

Complete State

<MessageStatus
  status="complete"
  text="Analysis complete"
/>

Error State

<MessageStatus
  status="error"
  text="Failed to process request"
/>

Multi-Step Status

Display progress across multiple steps:

<MessageStatus
  status="loading"
  text="Processing request"
  steps={[
    { id: '1', text: 'Validating input', status: 'complete' },
    { id: '2', text: 'Fetching data', status: 'complete' },
    { id: '3', text: 'Analyzing results', status: 'loading' },
    { id: '4', text: 'Generating report', status: 'loading' }
  ]}
/>

Using in Conversations

Embed status indicators in conversation responses:

Loading status indicator would appear here...

Advanced Examples

Dynamic Status Updates

Update status as operations progress:

import { useState, useEffect } from 'react';
import { MessageStatus } from 'reachat';
 
function AnalysisStatus() {
  const [steps, setSteps] = useState([
    { id: '1', text: 'Initializing', status: 'loading' },
    { id: '2', text: 'Processing data', status: 'loading' },
    { id: '3', text: 'Generating insights', status: 'loading' }
  ]);
 
  useEffect(() => {
    // Simulate progress
    const timers = [
      setTimeout(() => updateStep('1', 'complete'), 1000),
      setTimeout(() => updateStep('2', 'complete'), 2000),
      setTimeout(() => updateStep('3', 'complete'), 3000)
    ];
 
    return () => timers.forEach(clearTimeout);
  }, []);
 
  const updateStep = (id: string, status: string) => {
    setSteps(prev => prev.map(step =>
      step.id === id ? { ...step, status } : step
    ));
  };
 
  const allComplete = steps.every(s => s.status === 'complete');
 
  return (
    <MessageStatus
      status={allComplete ? 'complete' : 'loading'}
      text={allComplete ? 'Analysis complete' : 'Running analysis'}
      steps={steps}
    />
  );
}

Error Handling

Display errors with specific step failures:

<MessageStatus
  status="error"
  text="Analysis failed"
  steps={[
    { id: '1', text: 'Load dataset', status: 'complete' },
    { id: '2', text: 'Validate schema', status: 'complete' },
    { id: '3', text: 'Run computation', status: 'error' }
  ]}
/>

Custom Icons

Provide custom icons for status states:

import { CheckCircle, XCircle, Loader } from 'lucide-react';
 
<MessageStatus
  status="loading"
  text="Custom status indicator"
  icon={<Loader className="animate-spin" />}
/>

Nested in Markdown

Include status indicators in markdown responses:

const conversationWithStatus = {
  id: '1',
  question: 'Run the analysis',
  response: `I'm running the analysis now.
 
<MessageStatus
  status="loading"
  text="Analyzing data"
  steps={[
    { id: '1', text: 'Loading dataset', status: 'complete' },
    { id: '2', text: 'Computing statistics', status: 'loading' }
  ]}
/>
 
I'll let you know when it's complete.`,
  createdAt: new Date('2024-01-15T10:00:00Z')
};

Integration with Custom Components

Use with custom markdown components:

import { Chat, MessageStatus } from 'reachat';
 
<Chat
  markdownComponents={{
    MessageStatus: (props) => (
      <MessageStatus
        {...props}
        className="my-custom-status"
      />
    )
  }}
>
  {/* ... */}
</Chat>

Real-World Example

Complete example with API integration:

import { useState } from 'react';
import { Chat, MessageStatus, ChatInput } from 'reachat';
 
function ChatWithStatus() {
  const [status, setStatus] = useState(null);
 
  const handleSubmit = async (message) => {
    setStatus({
      status: 'loading',
      text: 'Processing request',
      steps: [
        { id: '1', text: 'Sending request', status: 'loading' },
        { id: '2', text: 'Waiting for response', status: 'loading' }
      ]
    });
 
    try {
      // Update first step
      setStatus(prev => ({
        ...prev,
        steps: prev.steps.map((s, i) =>
          i === 0 ? { ...s, status: 'complete' } : s
        )
      }));
 
      const response = await fetch('/api/chat', {
        method: 'POST',
        body: JSON.stringify({ message })
      });
 
      // Update second step
      setStatus(prev => ({
        ...prev,
        steps: prev.steps.map((s, i) =>
          i === 1 ? { ...s, status: 'complete' } : s
        )
      }));
 
      const data = await response.json();
 
      setStatus({
        status: 'complete',
        text: 'Response received',
        steps: prev.steps
      });
 
    } catch (error) {
      setStatus({
        status: 'error',
        text: 'Request failed',
        steps: prev.steps.map(s => ({ ...s, status: 'error' }))
      });
    }
  };
 
  return (
    <Chat sessions={sessions}>
      <SessionMessagePanel>
        <SessionMessages />
        {status && <MessageStatus {...status} />}
        <ChatInput onSubmit={handleSubmit} />
      </SessionMessagePanel>
    </Chat>
  );
}

API Reference

MessageStatusProps

interface MessageStatusProps {
  status?: 'loading' | 'complete' | 'error'; // Default: 'loading'
  text: string; // Main status text
  steps?: MessageStatusStep[]; // Optional sub-steps
  icon?: ReactNode; // Custom icon
  className?: string; // Additional CSS class
}

MessageStatusStep

interface MessageStatusStep {
  id: string; // Unique identifier
  text: string; // Step description
  status?: 'loading' | 'complete' | 'error'; // Default: 'loading'
}

For more examples and interactive demos, visit the storybook demos (opens in a new tab).