react-markdown-messages
v0.1.0
Published
A lightweight, streaming-first React component library for rendering markdown messages with syntax highlighting, math support, task lists, and more.
Maintainers
Readme
react-markdown-messages
A lightweight, streaming-first React component library for rendering markdown messages with syntax highlighting, math support, task lists, and more. Built for AI chat interfaces.
Features
- Streaming Support — Render markdown in real-time as text streams in, no waiting for completion
- Syntax Highlighting — 190+ languages supported via highlight.js
- KaTeX Math — Beautiful LaTeX math rendering with inline and block equations
- Interactive Task Lists — Clickable checkboxes with change callbacks
- Code Editing — Edit code blocks inline with copy and collapse
- RTL Support — Full right-to-left language support for Arabic, Hebrew, and more
- TypeScript — Written in TypeScript with full type definitions
- Zero External UI Dependencies — No heavy UI framework required
Installation
npm install react-markdown-messagesOr with your favorite package manager:
pnpm add react-markdown-messages
yarn add react-markdown-messages
bun add react-markdown-messagesQuick Start
Basic Usage
import { Markdown } from 'react-markdown-messages';
function App() {
return (
<Markdown
content="# Hello World\n\nThis is **streaming** markdown!"
done={true}
/>
);
}Streaming Example
import { useState, useEffect } from 'react';
import { Markdown } from 'react-markdown-messages';
function StreamingChat() {
const [content, setContent] = useState('');
const [done, setDone] = useState(false);
useEffect(() => {
const text = 'Your streaming content here...';
let i = 0;
const interval = setInterval(() => {
if (i < text.length) {
setContent(text.slice(0, ++i));
} else {
setDone(true);
clearInterval(interval);
}
}, 50);
return () => clearInterval(interval);
}, []);
return <Markdown content={content} done={done} />;
}With Chat Messages
import { Messages } from 'react-markdown-messages';
function Chat() {
const messages = [
{ id: '1', role: 'user', content: 'Hello!' },
{ id: '2', role: 'assistant', content: 'Hi there!' },
];
return (
<Messages
messages={messages}
onEdit={(id, content) => console.log(id, content)}
onDelete={(id) => console.log('delete', id)}
onRate={(id, rating) => console.log(id, rating)}
/>
);
}Components
<Markdown />
Core markdown rendering component.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| id | string | '' | Unique identifier |
| content | string | — | Markdown content |
| done | boolean | true | Streaming complete flag |
| model | string | null | Model name to display |
| editCodeBlock | boolean | true | Allow code editing |
| paragraphTag | 'p' \| 'span' | 'p' | Paragraph element type |
| onTaskClick | function | — | Task list checkbox callback |
| onSourceClick | function | — | Citation click callback |
| onSave | function | — | Code save callback |
<Messages />
Complete chat message list component with auto-scroll.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| messages | MessageType[] | — | Array of messages |
| autoScroll | boolean | true | Auto-scroll to bottom |
| onEdit | function | — | Message edit callback |
| onDelete | function | — | Message delete callback |
| onRate | function | — | Message rating callback |
| onRegenerate | function | — | Regenerate response callback |
| onContinue | function | — | Continue generating callback |
| editCodeBlock | boolean | true | Allow code editing |
| readOnly | boolean | false | Disable all interactions |
<CodeBlock />
Standalone code block component with syntax highlighting, editing, and collapse.
<useStreaming /> Hook
Simulate streaming text output for demos.
const { content, isStreaming, progress, start, stop, reset } = useStreaming(initialContent, {
speed: 100, // characters per second
chunkSize: 5, // characters per chunk
onComplete: () => console.log('Done!'),
});API Reference
Types
interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
model?: string;
timestamp?: number;
files?: { type: string; url: string }[];
annotation?: {
rating?: number;
};
}
interface MarkdownProps {
id?: string;
content: string;
done?: boolean;
model?: string | null;
editCodeBlock?: boolean;
paragraphTag?: 'p' | 'span';
sourceIds?: string[];
onSave?: (data: { raw: string; oldContent: string; newContent: string }) => void;
onUpdate?: () => void;
onPreview?: () => void;
onSourceClick?: (sourceId: string) => void;
onTaskClick?: (data: TaskClickData) => void;
}Peer Dependencies
{
"peerDependencies": {
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
}
}License
MIT
