@jazzmine-ui/react
v0.1.13
Published
Jazzmine: A customizable React chat UI component library
Maintainers
Readme
@jazzmine-ui/react
Production-ready React chat UI for the Jazzmine ecosystem.
This package is the UI layer for Jazzmine apps. It provides composable chat components, a managed SDK-powered experience, and a strongly typed contract for backend clients.
Package: @jazzmine-ui/react
Version: 0.1.10
Runtime: React 18+
Overview
@jazzmine-ui/react supports two integration styles:
JazzmineChat: managed mode that handles conversation lifecycle and message flow.ChatInterface: controlled mode where your app owns data fetching and state.
Both modes share the same visual system and core message/context model.
Package Role In The Ecosystem
This package is responsible for UI and interaction orchestration:
- Renders chat layouts, message streams, sidebars, and search UI.
- Maps backend conversation/message data into UI state.
- Exposes reusable components for custom app-level composition.
- Stays SDK-agnostic at runtime: any client matching
IJazzmineClientworks.
Install
npm install @jazzmine-ui/reactInstall peer dependencies if your app does not already provide them:
npm install react react-dom react-markdown remark-gfm remark-math rehype-katex katexImport package styles once at app entry:
import '@jazzmine-ui/react/styles';Choose An Integration Mode
| Mode | Best for | You manage | Package manages |
| --- | --- | --- | --- |
| JazzmineChat | Fastest production integration | Client instance + optional callbacks | Conversation create/list/search/delete/update, history loading, send flow, loading states |
| ChatInterface | Full custom state architecture | All data/state/actions | Presentation, local UI interactions, context selection UX |
Key Features
- Managed conversation flows (create/select/rename/delete).
- Sidebar pagination and search modal integration.
- Markdown + GFM + LaTeX rendering (
react-markdown+remark-gfm+remark-math+rehype-katex). - Explicit context selection and forwarding support.
- Empty-state assistant message via
defaultMessage. - History mapping based on backend
original_content. - Optional history context hydration from backend
explicit_context.
Quick Start
1) SDK-Powered With JazzmineChat
'use client';
import React from 'react';
import JazzmineClient from '@jazzmine-ui/sdk';
import { JazzmineChat } from '@jazzmine-ui/react';
import '@jazzmine-ui/react/styles';
const client = new JazzmineClient('https://your-jazzmine-api.example.com', {
apiKey: 'your-api-key',
defaultUserId: 'user',
});
export function App() {
return (
<div style={{ height: '100vh' }}>
<JazzmineChat
client={client}
assistantName="Jazzmine AI"
placeholder="Ask anything..."
defaultMessage="Welcome! Ask me anything to get started."
onError={(error) => {
console.error('JazzmineChat error:', error);
}}
/>
</div>
);
}2) Fully Controlled With ChatInterface
import React from 'react';
import { ChatInterface } from '@jazzmine-ui/react';
import type { Chat, Message } from '@jazzmine-ui/react';
import '@jazzmine-ui/react/styles';
export function App() {
const [messages, setMessages] = React.useState<Message[]>([]);
const [chats, setChats] = React.useState<Chat[]>([]);
const [activeChatId, setActiveChatId] = React.useState<string>();
const [isLoading, setIsLoading] = React.useState(false);
const onSend = async (text: string) => {
setMessages((prev) => [
...prev,
{ id: crypto.randomUUID(), text, sender: 'user', timestamp: new Date().toISOString() },
]);
setIsLoading(true);
try {
const reply = `Echo: ${text}`;
setMessages((prev) => [
...prev,
{
id: crypto.randomUUID(),
text: reply,
sender: 'assistant',
timestamp: new Date().toISOString(),
},
]);
} finally {
setIsLoading(false);
}
};
return (
<div style={{ height: '100vh' }}>
<ChatInterface
chats={chats}
activeChatId={activeChatId}
messages={messages}
onSend={onSend}
onNewChat={() => {}}
onSelectChat={setActiveChatId}
isLoading={isLoading}
defaultMessage="Welcome! Ask me anything to get started."
/>
</div>
);
}Public Exports
Components:
ChatInterfaceSidebarMessageListFloatingChatWidgetJazzmineChatSearchModal
Types:
ChatInterfacePropsSidebarPropsMessageListPropsFloatingChatWidgetPropsJazzmineChatPropsSearchModalPropsIJazzmineClientContextMessageChat
API Reference
JazzmineChatProps
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| client | IJazzmineClient | Yes | - | Backend client implementation. |
| userId | string | No | 'user' | Used for list/search conversation calls. |
| assistantName | string | No | Health response or 'AI Assistant' | Header/avatar assistant label. |
| placeholder | string | No | 'Type your message...' | Input placeholder text. |
| className | string | No | '' | Root class override. |
| defaultMessage | string | No | '' | Rendered when conversation has no messages and is not loading. |
| onError | (error: Error) => void | No | - | Called for recoverable client-side errors. |
ChatInterfaceProps
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| messages | Message[] | Yes | - | Current message list. |
| chats | Chat[] | Yes | - | Sidebar conversation list. |
| onSend | (text: string, contexts?: Context[]) => void | Yes | - | Send handler; receives selected context snippets when present. |
| onNewChat | () => void | Yes | - | New chat action. |
| onSelectChat | (chatId: string) => void | Yes | - | Active chat selection. |
| activeChatId | string | No | - | Active conversation id. |
| assistantName | string | No | 'AI Assistant' | Assistant display name. |
| onRenameChat | (chatId: string, newTitle?: string) => void | No | - | Rename conversation action. |
| onDeleteChat | (chatId: string) => void | No | - | Delete conversation action. |
| onSearchClick | () => void | No | - | Opens external conversation search flow. |
| onLoadMore | () => void | No | - | Load-more trigger for infinite conversation lists. |
| hasMore | boolean | No | false | Indicates additional chat pages are available. |
| isLoadingChats | boolean | No | false | Sidebar list loading indicator. |
| isSearchOpen | boolean | No | false | Controls sidebar search visibility. |
| searchQuery | string | No | '' | Sidebar search query value. |
| onSearchQueryChange | (query: string) => void | No | - | Sidebar search input handler. |
| isLoading | boolean | No | false | Message send/load state. |
| loadingText | string | No | '' | Assistant status text while loading. |
| loadingVariant | 'text-and-dots' \| 'dots-only' | No | 'text-and-dots' | Loading indicator style. |
| placeholder | string | No | 'Type your message...' | Input placeholder text. |
| className | string | No | '' | Root class override. |
| defaultMessage | string | No | '' | Empty-state assistant message. |
SidebarProps
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| chats | Chat[] | Yes | - | Conversations to render. |
| onNewChat | () => void | Yes | - | New chat button callback. |
| onSelectChat | (chatId: string) => void | Yes | - | Select chat callback. |
| activeChatId | string | No | - | Current selected chat id. |
| assistantName | string | No | - | Header title label. |
| logo | string | No | Built-in logo | Custom header/logo image. |
| logoAlt | string | No | - | Logo alt text. |
| chatActions | ChatAction[] | No | Built-in actions | Custom chat action menu items. |
| onRenameChat | (chatId: string, newTitle?: string) => void | No | - | Enables default rename action. |
| onDeleteChat | (chatId: string) => void | No | - | Enables default delete action. |
| onArchiveChat | (chatId: string) => void | No | - | Enables default archive action. |
| onSearchClick | () => void | No | - | Search trigger callback. |
| onLoadMore | () => void | No | - | Infinite-scroll load callback. |
| hasMore | boolean | No | false | More pages available. |
| isLoadingChats | boolean | No | false | Loading state for chat list. |
| isSearchOpen | boolean | No | false | Search input visibility. |
| searchQuery | string | No | '' | Search query value. |
| onSearchQueryChange | (query: string) => void | No | - | Search query change callback. |
| className | string | No | '' | Root class override. |
| collapsed | boolean | No | Internal state | Controlled collapse mode. |
| onToggleCollapse | (value?: boolean) => void | No | - | Controlled collapse handler. |
MessageListProps
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| messages | Message[] | Yes | - | Message feed data. |
| assistantName | string | No | - | Assistant label in assistant messages. |
| defaultMessage | string | No | '' | Empty-state assistant message. |
| isLoading | boolean | No | false | Appends loading assistant row. |
| loadingText | string | No | 'typing' | Loading indicator text. |
| loadingVariant | 'text-and-dots' \| 'dots-only' | No | 'text-and-dots' | Loading indicator style. |
| className | string | No | '' | Root class override. |
| searchQuery | string | No | - | Highlight query string. |
| activeSearchMessageId | string | No | - | Auto-scroll target message id. |
| onAddContext | (context: Context) => void | No | - | Adds selected snippet to context panel. |
| scrollRef | React.RefObject<HTMLDivElement \| null> \| ((node: HTMLDivElement \| null) => void) | No | - | External scroll node access. |
FloatingChatWidgetProps
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| messages | Message[] | Yes | - | Message feed data. |
| assistantName | string | No | - | Header title in widget panel. |
| isLoading | boolean | No | false | Loading state. |
| loadingText | string | No | 'typing' | Loading text. |
| loadingVariant | 'text-and-dots' \| 'dots-only' | No | 'text-and-dots' | Loading indicator style. |
| initialOpen | boolean | No | false | Initial panel open state. |
| onOpen | (open: boolean) => void | No | - | Open/close change callback. |
| onSend | (text: string) => void | No | - | Message send callback. |
| logo | string | No | Built-in logo | Widget button image source. |
| className | string | No | '' | Root class override. |
SearchModalProps
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| isOpen | boolean | Yes | - | Modal visibility state. |
| onClose | () => void | Yes | - | Close callback. |
| onSelectConversation | (conversationId: string) => void | Yes | - | Select result callback. |
| searchQuery | string | Yes | - | Controlled input value. |
| onSearchQueryChange | (query: string) => void | Yes | - | Controlled input update callback. |
| results | Chat[] | Yes | - | Search results. |
| isSearching | boolean | Yes | - | Loading state for async search. |
ChatAction
interface ChatAction {
label: string;
icon?: React.ReactNode;
onClick: (chatId: string) => void;
danger?: boolean;
}IJazzmineClient Contract
JazzmineChat depends on this contract and does not require a specific concrete implementation.
interface IJazzmineClient {
sendMessage(
message: string,
options?: {
conversationId?: string;
autoCreateConversation?: boolean;
conversationTitle?: string;
explicitContext?: string[];
}
): Promise<{
response: {
response: string;
response_markdown: string;
conversation_id: string;
message_id: string;
is_blocked: boolean;
errors: string[];
};
conversationId: string;
}>;
createConversation(payload?: { title?: string; user_id?: string }): Promise<{
conversation_id: string;
title: string;
}>;
deleteConversation(conversationId: string): Promise<{
conversation_id: string;
deleted: boolean;
}>;
listConversations(params: {
userId: string;
limit?: number;
offset?: number;
}): Promise<{
conversations: Array<{
conversation_id: string;
title: string;
last_updated_at: number;
}>;
total: number;
hasMore: boolean;
offset: number;
limit: number;
}>;
searchConversations(params: {
userId: string;
query: string;
limit?: number;
offset?: number;
}): Promise<{
conversations: Array<{
conversation_id: string;
title: string;
last_updated_at: number;
}>;
total: number;
hasMore: boolean;
offset: number;
limit: number;
query?: string;
}>;
updateConversation(
conversationId: string,
payload: { title: string }
): Promise<{
conversation_id: string;
title: string;
last_updated_at: number;
}>;
getConversationMessages(params: {
conversationId: string;
limit?: number;
offset?: number;
}): Promise<{
conversation_id: string;
messages: Array<{
id: string;
role: 'user' | 'assistant' | 'colleague_assistant' | 'system';
original_content: string;
enhanced_message: string;
explicit_context?: string[] | null;
timestamp: number;
}>;
total: number;
hasMore: boolean;
}>;
getHealth(): Promise<{
status: string;
agent_name: string;
}>;
}Data Mapping Notes (JazzmineChat)
When loading historical messages, JazzmineChat intentionally applies these rules:
- Only
userandassistantroles are rendered. - Message text is sourced from
original_content. explicit_contextis mapped intoMessage.contextswhen non-empty.- If
explicit_contextis missing or empty,contextsis omitted.
Theming
The package uses CSS variables. Override them globally after importing styles:
:root {
--jazzmine-primary: #3b82f6;
--jazzmine-primary-hover: #2563eb;
--jazzmine-bg: #f8fafc;
--jazzmine-text-primary: #0f172a;
--jazzmine-border-radius: 14px;
--jazzmine-sidebar-width: 300px;
}Development
npm install
npm run lint
npm run buildChangelog
0.1.10
- Synced SDK history contract docs with
explicit_contextsupport. - Exported
Contextin the package type barrel and docs export list. - Updated README package version metadata.
0.1.9
- Added empty-state
defaultMessagesupport in chat flow. - Improved history mapping to use
original_contentas message text. - Added support for mapping backend
explicit_contextto message contexts. - Expanded README structure for ecosystem docs pages.
0.1.8
- Added
defaultMessageprop toJazzmineChatandChatInterfacepathways. - Updated docs and usage examples.
0.1.7
- Added conversation search modal and sidebar search integration.
- Added pagination/load-more behavior in sidebar.
- Added rename and delete flows for conversations.
License
MIT
