npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ainative/aikit-react

v0.1.0

Published

React components for AI-powered streaming interfaces

Readme

@aikit/react

React components for building AI-powered streaming interfaces with smooth animations and markdown support.

Features

  • Streaming Message Component: Display AI messages with real-time streaming support
  • Token-by-Token Animations: Smooth typewriter and fade-in effects for new tokens
  • Markdown Rendering: Full markdown support with GFM (GitHub Flavored Markdown)
  • Syntax Highlighting: Beautiful code blocks with multiple themes
  • Accessible: WCAG 2.1 AA compliant with proper ARIA attributes
  • Responsive: Mobile-first design that works on all screen sizes
  • TypeScript: Fully typed with comprehensive TypeScript definitions
  • Customizable: Extensive props for styling and behavior customization

Installation

npm install @aikit/react

Or with yarn:

yarn add @aikit/react

Peer Dependencies

This package requires React 18+ as a peer dependency:

npm install react react-dom

Quick Start

import { StreamingMessage } from '@aikit/react';

function ChatInterface() {
  const [message, setMessage] = useState('');

  return (
    <StreamingMessage
      role="assistant"
      content={message}
      streamingState="streaming"
      enableMarkdown={true}
      animationType="typewriter"
    />
  );
}

Components

StreamingMessage

The main component for displaying AI messages with streaming support.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | role | 'user' \| 'assistant' \| 'system' | Required | Message sender role | | content | string | Required | Message content (can be partial during streaming) | | streamingState | 'idle' \| 'streaming' \| 'complete' \| 'error' | 'idle' | Current streaming state | | animationType | 'none' \| 'fade' \| 'typewriter' \| 'smooth' | 'smooth' | Animation type for new tokens | | animationSpeed | number | 30 | Animation speed in ms per character | | enableMarkdown | boolean | true | Enable markdown rendering | | codeTheme | 'dark' \| 'light' \| 'vs-dark' \| 'github' \| 'monokai' \| 'nord' \| 'dracula' | 'dark' | Code syntax highlighting theme | | showStreamingIndicator | boolean | true | Show streaming indicator | | className | string | '' | Custom CSS class | | style | CSSProperties | - | Custom inline styles | | avatar | string \| ReactNode | - | Avatar URL or custom element | | displayName | string | - | Display name for message sender | | showTimestamp | boolean | false | Show message timestamp | | metadata | MessageMetadata | - | Additional message metadata | | onStreamingComplete | () => void | - | Callback when streaming completes | | onContentUpdate | (content: string) => void | - | Callback on content updates | | onError | (error: Error) => void | - | Error handler | | enableCodeCopy | boolean | true | Enable copy button for code blocks | | roleColors | object | - | Custom colors for each role | | testId | string | 'streaming-message' | Test ID for testing |

Examples

Basic Usage

<StreamingMessage
  role="assistant"
  content="Hello! How can I help you today?"
  streamingState="complete"
/>

With Streaming Animation

<StreamingMessage
  role="assistant"
  content={streamingContent}
  streamingState="streaming"
  animationType="typewriter"
  animationSpeed={20}
  showStreamingIndicator={true}
/>

With Markdown and Code Highlighting

<StreamingMessage
  role="assistant"
  content={`
# Code Example

Here's a JavaScript function:

\`\`\`javascript
function greet(name) {
  return \`Hello, \${name}!\`;
}
\`\`\`
  `}
  enableMarkdown={true}
  codeTheme="dracula"
  enableCodeCopy={true}
/>

With Avatar and Metadata

<StreamingMessage
  role="assistant"
  content="Processing your request..."
  avatar="https://example.com/bot-avatar.png"
  displayName="AI Assistant"
  showTimestamp={true}
  metadata={{
    timestamp: new Date(),
    model: 'gpt-4',
    tokensUsed: 150
  }}
/>

With Custom Styling

<StreamingMessage
  role="user"
  content="What's the weather like?"
  className="custom-message"
  style={{ maxWidth: '600px' }}
  roleColors={{
    user: '#2196F3',
    assistant: '#4CAF50',
    system: '#FF9800'
  }}
/>

With Callbacks

<StreamingMessage
  role="assistant"
  content={content}
  streamingState={streamingState}
  onStreamingComplete={() => {
    console.log('Streaming completed!');
    saveMessage();
  }}
  onContentUpdate={(newContent) => {
    console.log('Content updated:', newContent);
  }}
  onError={(error) => {
    console.error('Streaming error:', error);
    handleError(error);
  }}
/>

StreamingIndicator

Animated indicator for showing streaming progress.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | variant | 'dots' \| 'pulse' \| 'wave' | 'dots' | Indicator style variant | | className | string | '' | Custom CSS class | | style | CSSProperties | - | Custom inline styles | | testId | string | 'streaming-indicator' | Test ID for testing |

Examples

import { StreamingIndicator } from '@aikit/react';

// Dots variant (default)
<StreamingIndicator variant="dots" />

// Pulse variant
<StreamingIndicator variant="pulse" />

// Wave variant
<StreamingIndicator variant="wave" />

// With custom styling
<StreamingIndicator
  variant="dots"
  style={{ color: '#3b82f6' }}
/>

CodeBlock

Syntax-highlighted code block with copy functionality.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | language | string | Required | Programming language | | children | string | Required | Code content | | theme | CodeTheme | 'dark' | Syntax highlighting theme | | enableCopy | boolean | true | Enable copy button | | className | string | '' | Custom CSS class | | showLineNumbers | boolean | true | Show line numbers |

Examples

import { CodeBlock } from '@aikit/react';

// JavaScript code
<CodeBlock language="javascript">
  {`function hello() {
    return "world";
  }`}
</CodeBlock>

// Python with custom theme
<CodeBlock language="python" theme="monokai">
  {`def greet(name):
    return f"Hello, {name}!"`}
</CodeBlock>

// Without copy button
<CodeBlock language="typescript" enableCopy={false}>
  {`const x: number = 42;`}
</CodeBlock>

Advanced Usage

Building a Chat Interface

import { useState, useEffect } from 'react';
import { StreamingMessage } from '@aikit/react';

interface ChatMessage {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  streaming?: boolean;
}

function ChatInterface() {
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [streamingContent, setStreamingContent] = useState('');

  const handleSendMessage = async (text: string) => {
    // Add user message
    const userMessage: ChatMessage = {
      id: Date.now().toString(),
      role: 'user',
      content: text,
    };
    setMessages(prev => [...prev, userMessage]);

    // Start streaming assistant response
    const assistantMessage: ChatMessage = {
      id: (Date.now() + 1).toString(),
      role: 'assistant',
      content: '',
      streaming: true,
    };
    setMessages(prev => [...prev, assistantMessage]);

    // Simulate streaming
    const fullResponse = await fetchAIResponse(text);
    for (let i = 0; i < fullResponse.length; i++) {
      setStreamingContent(fullResponse.slice(0, i + 1));
      await new Promise(resolve => setTimeout(resolve, 20));
    }

    // Complete streaming
    setMessages(prev =>
      prev.map(msg =>
        msg.id === assistantMessage.id
          ? { ...msg, content: fullResponse, streaming: false }
          : msg
      )
    );
  };

  return (
    <div className="chat-container">
      {messages.map(message => (
        <StreamingMessage
          key={message.id}
          role={message.role}
          content={message.streaming ? streamingContent : message.content}
          streamingState={message.streaming ? 'streaming' : 'complete'}
          enableMarkdown={true}
          animationType="typewriter"
          showTimestamp={true}
          metadata={{
            timestamp: new Date(),
          }}
        />
      ))}
    </div>
  );
}

Custom Animation Timing

<StreamingMessage
  role="assistant"
  content={content}
  streamingState="streaming"
  animationType="typewriter"
  animationSpeed={15} // Faster animation (15ms per character)
/>

Handling Different Message Types

function MessageRenderer({ message }) {
  const getAnimationType = (role) => {
    switch (role) {
      case 'user':
        return 'none'; // No animation for user messages
      case 'assistant':
        return 'typewriter'; // Typewriter for AI responses
      case 'system':
        return 'fade'; // Fade for system messages
      default:
        return 'smooth';
    }
  };

  return (
    <StreamingMessage
      role={message.role}
      content={message.content}
      streamingState={message.streamingState}
      animationType={getAnimationType(message.role)}
      roleColors={{
        user: '#3b82f6',
        assistant: '#10b981',
        system: '#f59e0b',
      }}
    />
  );
}

TypeScript Support

All components are fully typed with TypeScript. Import types as needed:

import type {
  StreamingMessageProps,
  MessageRole,
  StreamingState,
  AnimationType,
  CodeTheme,
  MessageMetadata,
} from '@aikit/react';

Accessibility

All components follow WCAG 2.1 AA guidelines:

  • Proper ARIA attributes for screen readers
  • Keyboard navigation support
  • Sufficient color contrast ratios
  • Descriptive labels for interactive elements
  • Status indicators for streaming states

Browser Support

  • Chrome/Edge: Last 2 versions
  • Firefox: Last 2 versions
  • Safari: Last 2 versions
  • Mobile browsers: iOS Safari 12+, Chrome Android

Testing

Components are tested with React Testing Library:

npm test
npm run test:coverage

Coverage threshold: 80%+ for all metrics.

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

License

MIT

Support

For issues and questions, please visit our GitHub repository or contact support.