Introduction
An unstyled React primitive library for building AI chat interfaces.
@intentface/chat is an unstyled React library for building chat interfaces. It
provides the behavior that chat UIs need and is hard to write — a rich-text
composer, scroll ownership, message segmentation, streaming disclosure — and
renders no styles of its own.
React and React DOM are the only peer dependencies. There is no editor framework underneath, no animation library, and no opinion about transport: the package never makes a request.
Features
Headless
The primitives are unstyled, bundle no CSS, and prescribe no styling solution.
They render semantic DOM with data-* state attributes, and every part accepts
className, style, and a render prop. See Styling.
Composable
Each primitive is a namespace of parts you assemble yourself — Composer.Root,
Composer.Container, Message.Root. Parts can be reordered, omitted, or wrapped,
and every one exposes its state through context hooks.
Built for streaming
The composer's editor is isolated from the message stream, so tokens arriving dozens of times a second don't re-render it. The thread follows new content while you're at the bottom and releases when you scroll away. See Composer performance.
AI SDK compatible
The package defines its own structural message types, which a Vercel AI SDK
UIMessage already satisfies — so SDK messages pass straight into the components
with no adapter.
Primitives
| Entry point | What it covers |
|---|---|
/composer | Contenteditable editor, inline chips, prefix command lists, attachments, ask-user flow |
/thread | Scroll container: at-bottom detection, auto-follow, dock measurement, prepend restoration |
/message | Message parts, turn grouping, chip-segmented text |
/steps | Collapsible timeline of a run: reasoning, tool calls and answered questions |
/reasoning | Reasoning disclosure that tracks streaming state and elapsed time |
/chip | Inline tokens for composer mentions and chips in messages |
/attachments | Attachment tray: items, remove, drop zone and file picker |
/ask-user | Parts for the questions a model asks the user |
/shell | Collapsible, resizable sidebar beside the viewport |
/nav | Nav tree with roving focus, typeahead and collapsible groups |
/tabs | Closable tabs whose panel renders in the layout or in a popover |
/types | The structural message contract |
/message-utils | Pure helpers over messages: part segments, turn grouping, text and file info |
/chip-markdown | Encode and parse the chip wire format inside message text |
Next steps
- Quick start — install the package and assemble a chat
- Build a chat — the same result in four stages
- Accessibility — what the primitives wire up, and what you supply