@tagit/ai-client-react
v0.5.0
Published
Self-contained React chat widget and hooks for TagIt AI client
Readme
@tagit/ai-client-react
React integration layer for tagIt AI.
Use this package when you want a self-contained chat experience in a React app. It builds on @tagit/ai-client-core, which owns the client engine, orchestrator transport, state, and collector emission. The core package README is the source of truth for those engine details.
What Is tagIt?
tagIt is the platform for building governed AI experiences. It gives teams a way to define AI use cases, connect models, optionally attach MCP servers, and shape the orchestration logic that drives the overall experience.
What Is the AI Orchestrator?
The AI Orchestrator is the runtime layer that executes a use case. It combines the configured model, optional tools and MCP servers, conversation context, and policy behavior to produce the response flow for a specific scenario.
Why These Packages Exist
The @tagit/ai-client-core and @tagit/ai-client-react packages are the client-side pieces of that system. They connect your app to a tagIt account and a configured orchestrator so you can embed AI experiences in a product or website.
You need a tagIt account and at least one configured use case before these packages can drive a real experience. MCP servers are optional, but they can extend the orchestrator with tools and external capabilities.
To learn more, visit tagit.live.
This README is the source of truth for integrating the React package.
What This Package Provides
AIClientProviderfor React contextuseAIClient,useConversation, anduseClientEventsChatWidgetfor a full embeddable chat shellChatConversationfor a lighter conversation surface- the widget stylesheet for direct import
Provider Contract
AIClientProvider is the only required wrapper.
| Field | Type | Required | What it does | Example |
|---|---|---:|---|---|
| client | AIClient | yes | The live client instance used by hooks and widgets below the provider. | client={client} |
| children | ReactNode | yes | The React subtree that receives AI client context. | <ChatWidget /> |
<AIClientProvider client={client}>
<ChatWidget />
</AIClientProvider>Public Imports
Supported public imports:
@tagit/ai-client-core@tagit/ai-client-core/config@tagit/ai-client-core/types@tagit/ai-client-react@tagit/ai-client-react/chat-widget@tagit/ai-client-react/chat-widget.css@tagit/ai-client-react/hooks@tagit/ai-client-react/provider@tagit/ai-client-react/conversation
Do not import from dist/* or from internal source paths.
Install
npm install @tagit/ai-client-core @tagit/ai-client-reactMinimal Working Example
This is the smallest known-good React embed.
import { AIClient, createDefaultConfig } from '@tagit/ai-client-core';
import { AIClientProvider, ChatWidget } from '@tagit/ai-client-react';
import '@tagit/ai-client-react/chat-widget.css';
const client = new AIClient(
createDefaultConfig('your-use-case-id', 'https://your-orchestrator.example.com', {
collector: {
enabled: false,
},
}),
);
export default function App() {
return (
<AIClientProvider client={client}>
<ChatWidget />
</AIClientProvider>
);
}If that exact example does not render the default empty state and footer, verify the package install and runtime config before customizing anything.
Core Concepts
@tagit/ai-client-core
This is the headless engine:
- orchestrator config and transport
- conversation state
- SSE streaming
- retry and timeout handling
- collector emission
@tagit/ai-client-react
This is the React shell:
- provider + hooks
- stock chat widget
- inline or overlay rendering
- shell styling and theming
Treat the core package as the engine and the React package as the UI layer on top.
Widget Modes
ChatWidget supports two modes:
mode="overlay"for floating chatmode="inline"for embedded layouts
For inline mode, there are two common host patterns:
dockMode="page"for a page-anchored raildockMode="viewport"for a viewport-docked rail that stays fixed to the browser edge
Use dockMode="viewport" when the widget should behave like a fixed browser sidebar and the host page should reserve layout space only while the panel is open. In this mode, the host page is responsible for the viewport split; the widget stays pinned to the browser edge and the tab collapses back to that edge.
Overlay Example
<ChatWidget
mode="overlay"
side="right"
title="tagIt Assistant"
showBackdrop
closeOnOutsideClick
/>Page-Rail Inline Example
<ChatWidget
mode="inline"
dockMode="page"
side="right"
open={true}
title="tagIt Assistant"
tabLabel="AI Client"
/>Viewport-Docked Inline Example
<ChatWidget
mode="inline"
dockMode="viewport"
side="right"
open={isOpen}
onOpenChange={setIsOpen}
title="tagIt Assistant"
tabLabel="AI Client"
tabHeightPercent={18}
width={440}
minWidthPx={360}
maxWidthPx={440}
/>Widget Configuration Dictionary
This section documents the public ChatWidget props that matter for integrations. If a field is omitted, the widget uses its built-in default.
Layout and shell fields
| Field | Type / values | Default | What it does | Example |
|---|---|---:|---|---|
| mode | 'overlay' \| 'inline' | overlay | Chooses between floating chat and embedded chat. | mode="inline" |
| dockMode | 'page' \| 'viewport' | page | Controls how inline mode is docked. page is a normal page rail. viewport pins the rail to the browser edge. | dockMode="viewport" |
| side | 'left' \| 'right' | right | Chooses which side the tab and panel live on. | side="right" |
| open | boolean | uncontrolled | Controlled open state. Use when the host needs to manage layout changes. | open={isOpen} |
| defaultOpen | boolean | false | Uncontrolled initial open state. | defaultOpen={true} |
| onOpenChange | (open: boolean) => void | undefined | Callback fired when the widget opens or closes. | onOpenChange={setIsOpen} |
| width | number \| string | 420 | Sets the panel width. Numbers are treated as pixels. | width={440} or width="32vw" |
| resizable | boolean | true | Enables or disables the drag resize handle. | resizable={false} |
| minWidthPx | number | 280 | Minimum panel width in pixels when resizing. | minWidthPx={360} |
| maxWidthPx | number | undefined | Maximum panel width in pixels when resizing. | maxWidthPx={520} |
| tabHeightPercent | number from 0 to 100 | 40 | Positions the tab vertically. 100 is near the top, 0 near the bottom. | tabHeightPercent={18} |
| className | string | undefined | Adds host styling hooks to the widget root. | className="product-rail" |
| children | ReactNode | undefined | Replaces the stock conversation body when intentionally supplied. | <CustomConversation /> |
Identity and labeling fields
| Field | Type / values | Default | What it does | Example |
|---|---|---:|---|---|
| title | string | Ask TagIt | Panel header title. | title="tagIt Assistant" |
| titleIconUrl | string \| null | undefined | Optional header icon URL. | titleIconUrl="/icons/agent.png" |
| tabLabel | string \| null | Chat | Text label on the tab. Set to null for icon-only mode. | tabLabel="AI Client" |
| tabIcon | ReactNode | 'AI' | Fallback tab icon/content when no icon URL is provided. | tabIcon={<Sparkles />} |
| tabIconUrl | string \| null | undefined | Optional image URL for the tab icon. | tabIconUrl="/icons/chat.png" |
| tabTooltipOpen | string \| null | derived | Tooltip shown when the widget is closed. | tabTooltipOpen="Open AI Client" |
| tabTooltipClose | string \| null | derived | Tooltip shown when the widget is open. | tabTooltipClose="Collapse AI Client" |
Theme and color fields
| Field | Type / values | Default | What it does | Example |
|---|---|---:|---|---|
| theme | 'light' \| 'dark' \| 'system' | system | Chooses the widget theme. system follows the OS preference. | theme="dark" |
| colorScheme | ChatColorScheme | undefined | Single theme palette for the widget. | { bg: '#0b1220', primary: '#60a5fa' } |
| colorSchemes | Partial<Record<'light' \| 'dark', ChatColorScheme>> | undefined | Separate palettes for light and dark themes. | { light: {...}, dark: {...} } |
Visibility and actions
| Field | Type / values | Default | What it does | Example |
|---|---|---:|---|---|
| showBackdrop | boolean | false | Shows the overlay scrim in overlay mode. | showBackdrop |
| closeOnOutsideClick | boolean | false | Allows clicking the backdrop to close the widget in overlay mode. | closeOnOutsideClick |
| onWidthChange | (width: string) => void | undefined | Called when the user resizes the panel. | onWidthChange={setWidth} |
| onNewChat | () => void | undefined | Overrides the default new-chat action. | onNewChat={handleNewChat} |
Open / Close Control
ChatWidget supports both controlled and uncontrolled open state.
open+onOpenChangefor controlled usagedefaultOpenfor uncontrolled usage
Use controlled state when the host page needs to:
- reserve layout space only while the panel is open
- coordinate open state with surrounding page layout
- keep the tab at the browser edge in a viewport-docked integration
Example: controlled viewport dock
const [isOpen, setIsOpen] = useState(true);
<ChatWidget
mode="inline"
dockMode="viewport"
side="right"
open={isOpen}
onOpenChange={setIsOpen}
title="tagIt Assistant"
tabLabel="AI Client"
/>Conversation Action Options
The useConversation() hook exposes sendMessage(), retry(), cancel(), clearHistory(), and reEditMessage(). The request option bag belongs to the core client and is documented in @tagit/ai-client-core.
ChatConversation
Use ChatConversation when you want a lighter conversation surface and you are already handling the shell yourself.
import { AIClientProvider, ChatConversation } from '@tagit/ai-client-react';
export default function App() {
return (
<AIClientProvider client={client}>
<ChatConversation />
</AIClientProvider>
);
}Use ChatWidget when you want the full built-in shell, header, tab, and sizing controls.
Custom Conversation Body
Only pass children to ChatWidget if you intentionally want to replace the built-in conversation body.
<ChatWidget mode="overlay" side="right" title="tagIt Assistant">
<CustomConversation />
</ChatWidget>If you do not pass children, the stock conversation UI is rendered automatically.
Configuration
The React package owns the widget shell, provider, hooks, and layout guidance. The core config, request, event, and collector contracts live in @tagit/ai-client-core.
Use the core README for:
createDefaultConfig()- orchestrator config
- collector config
- UI config
sendMessage()/retry()option bags- conversation state
- client events
- orchestrator request shape
- collector envelope shape
See packages/ai-client-core/README.md.
Starter Harness
The starter app in apps/starter is the local demo and shell playground.
Use it to test:
- overlay mode
- inline page-rail mode
- inline viewport-docked mode
- theming and color schemes
- tab labels and tooltips
- open/close behavior
- sizing and resize behavior
The starter is not the distributable package.
Recommended Integration Patterns
Simple Embed
Use this when you want the fastest possible install:
- create one
AIClient - wrap the app with
AIClientProvider - render
<ChatWidget /> - import
@tagit/ai-client-react/chat-widget.css
Viewport-Docked Sidebar
Use this when the chat should feel like a persistent product rail:
- keep the widget fixed to the browser edge
- reserve page width only when open
- let the tab collapse back to the browser edge
- keep the host page scroll independent of the rail
This pattern pairs best with:
mode="inline"dockMode="viewport"- controlled
openstate - host-page padding or content width reservation that only applies while the panel is open
<div className={`page-shell ${isOpen ? 'page-shell-chat-open' : ''}`}>
<main>...</main>
<ChatWidget
mode="inline"
dockMode="viewport"
side="right"
open={isOpen}
onOpenChange={setIsOpen}
/>
</div>Custom Shell
Use useConversation() when the host app wants to render its own shell and only consume conversation state and actions.
Troubleshooting
| Symptom | Likely cause | Check |
|---|---|---|
| Header/tab only, empty shell | stale package cache or old bundle | clear node_modules/.vite, restart dev server, confirm children is not being passed |
| No styling | CSS not imported | verify @tagit/ai-client-react/chat-widget.css import |
| Missing body after passing custom JSX | children overrides stock body | remove children to restore the stock widget |
| No messages sent | invalid orchestrator config | verify orchestrator.baseUrl and useCaseId, confirm baseUrl does not include /v1/chat |
| Runtime import error | unsupported import path | use only documented public exports |
| Collector events do not appear | collector config incomplete or disabled | confirm collector.enabled, collector.baseUrl, and collector.tagId |
| Inline mode looks cramped | panel width too small | pass a wider width or switch to dockMode="viewport" with host-side reserved space |
| Viewport-docked mode takes over the whole page | host layout is stretching the widget root | keep the docked widget fixed to the viewport edge and reserve page width only in the host shell |
