# Primitives
URL: /docs/ink/primitives
Composable terminal components for building chat UIs with Ink.
Primitives are thin wrappers around Ink components (`Box`, `Text`, `TextInput`) that integrate with the assistant-ui runtime. They accept all standard Ink props and add runtime-aware behavior.
Primitives are exported directly from `@assistant-ui/react-ink` (e.g. `ThreadRoot`, `ComposerInput`), unlike the web package which uses namespace imports.
Many primitives share their core logic with `@assistant-ui/react` via `@assistant-ui/core/react` — only the UI layer (Ink vs DOM) differs.
Thread \[#thread]
```tsx
import {
ThreadRoot,
ThreadMessages,
ThreadEmpty,
ThreadIf,
} from "@assistant-ui/react-ink";
```
ThreadRoot \[#threadroot]
Container `Box` for the thread area.
```tsx
{children}
```
| Prop | Type | Description |
| --------- | ---------- | ---------------------- |
| `...rest` | `BoxProps` | Standard Ink Box props |
ThreadMessages \[#threadmessages]
Renders the message list with automatic runtime integration. Each message is wrapped in a scoped context so that `useAuiState((s) => s.message)` works inside `renderMessage`.
```tsx
}
/>
```
| Prop | Type | Description |
| --------------- | ------------------------------------------------------------------- | ---------------- |
| `renderMessage` | `(info: { message: ThreadMessage; index: number }) => ReactElement` | Message renderer |
ThreadEmpty \[#threadempty]
Renders children only when the thread has no messages.
```tsx
Send a message to get started
```
ThreadIf \[#threadif]
Conditional rendering based on thread state.
```tsx
No messages yet
Generating...
```
| Prop | Type | Description |
| --------- | --------- | ----------------------------- |
| `empty` | `boolean` | Render when thread is empty |
| `running` | `boolean` | Render when thread is running |
ThreadSuggestion \[#threadsuggestion]
Renders a suggestion button. Uses Ink `Box` + `Text`.
```tsx
```
| Prop | Type | Description |
| ---------- | ----------------------- | ---------------------------------- |
| `prompt` | `string` | The suggestion text |
| `method` | `"replace" \| "append"` | How to insert the suggestion |
| `autoSend` | `boolean` | Automatically send after inserting |
Composer \[#composer]
```tsx
import {
ComposerRoot,
ComposerInput,
ComposerSend,
ComposerCancel,
ComposerAddAttachment,
ComposerAttachments,
ComposerIf,
} from "@assistant-ui/react-ink";
```
ComposerRoot \[#composerroot]
Container `Box` for the composer area.
```tsx
{children}
```
ComposerInput \[#composerinput]
Ink `TextInput` wired to the composer runtime. Value is managed automatically.
```tsx
```
| Prop | Type | Description |
| --------------- | --------- | ------------------------------------------------- |
| `submitOnEnter` | `boolean` | Whether Enter sends the message (default: `true`) |
| `placeholder` | `string` | Placeholder text when empty |
| `autoFocus` | `boolean` | Auto-focus on mount |
ComposerSend \[#composersend]
`Box` that triggers sending the current message. Typically used with a button-like UI.
```tsx
[Send]
```
ComposerCancel \[#composercancel]
`Box` that cancels the current run.
```tsx
[Stop]
```
ComposerAttachments \[#composerattachments]
Renders composer attachments using the provided component configuration.
```tsx
```
| Prop | Type | Description |
| ------------ | ------------------------------------------- | -------------------------------------- |
| `components` | `{ Image?, Document?, File?, Attachment? }` | Component renderers by attachment type |
ComposerAddAttachment \[#composeraddattachment]
Triggers attachment addition.
```tsx
[Attach]
```
ComposerIf \[#composerif]
Conditional rendering based on composer state. Shared from `@assistant-ui/core/react`.
```tsx
Currently editing
```
| Prop | Type | Description |
| --------- | --------- | --------------------------------------- |
| `editing` | `boolean` | Render when composer is in editing mode |
Message \[#message]
```tsx
import {
MessageRoot,
MessageContent,
MessageIf,
MessageParts,
MessageAttachments,
} from "@assistant-ui/react-ink";
```
MessageRoot \[#messageroot]
Container `Box` for a single message.
```tsx
{children}
```
MessageContent \[#messagecontent]
Renders message content parts. Tool call and data parts automatically render registered tool UIs (via `useAssistantTool` / `useAssistantDataUI`), falling back to render props if provided.
```tsx
{part.text}}
renderToolCall={({ part }) => [Tool: {part.toolName}]}
/>
```
| Prop | Type | Description |
| ----------------- | ------------------------------------------ | ----------------------- |
| `renderText` | `(props: { part; index }) => ReactElement` | Text part renderer |
| `renderToolCall` | `(props: { part; index }) => ReactElement` | Tool call fallback |
| `renderImage` | `(props: { part; index }) => ReactElement` | Image part renderer |
| `renderReasoning` | `(props: { part; index }) => ReactElement` | Reasoning part renderer |
| `renderSource` | `(props: { part; index }) => ReactElement` | Source part renderer |
| `renderFile` | `(props: { part; index }) => ReactElement` | File part renderer |
| `renderData` | `(props: { part; index }) => ReactElement` | Data part fallback |
MessageIf \[#messageif]
Conditional rendering based on message properties.
```tsx
You:
Thinking...
```
| Prop | Type | Description |
| ----------- | --------- | -------------------------------------- |
| `user` | `boolean` | Render for user messages |
| `assistant` | `boolean` | Render for assistant messages |
| `running` | `boolean` | Render when message is being generated |
| `last` | `boolean` | Render for the last message |
MessageAttachments \[#messageattachments]
Renders user message attachments using the provided component configuration.
```tsx
[{attachment.name}],
}}
/>
```
| Prop | Type | Description |
| ------------ | ------------------------------------------- | -------------------------------------- |
| `components` | `{ Image?, Document?, File?, Attachment? }` | Component renderers by attachment type |
Attachment \[#attachment]
```tsx
import {
AttachmentRoot,
AttachmentName,
AttachmentThumb,
AttachmentRemove,
} from "@assistant-ui/react-ink";
```
Primitives for rendering individual attachments.
AttachmentRoot \[#attachmentroot]
Container `Box` for an attachment.
AttachmentName \[#attachmentname]
`Text` component displaying the attachment filename.
AttachmentThumb \[#attachmentthumb]
`Text` component displaying the file extension.
AttachmentRemove \[#attachmentremove]
Pressable that removes the attachment from the composer.
```tsx
[x]
```
ActionBar \[#actionbar]
```tsx
import {
ActionBarCopy,
ActionBarEdit,
ActionBarReload,
ActionBarFeedbackPositive,
ActionBarFeedbackNegative,
} from "@assistant-ui/react-ink";
```
ActionBarCopy \[#actionbarcopy]
Pressable that copies the message content. Supports function-as-children for copy state feedback.
```tsx
{({ isCopied }) => {isCopied ? "[Copied!]" : "[Copy]"}}
```
| Prop | Type | Description |
| ----------------- | ------------------------ | ----------------------------------------------------- |
| `copiedDuration` | `number` | Duration in ms to show "copied" state (default: 3000) |
| `copyToClipboard` | `(text: string) => void` | Custom clipboard function |
ActionBarEdit \[#actionbaredit]
Pressable that enters edit mode for a message.
```tsx
[Edit]
```
ActionBarReload \[#actionbarreload]
Pressable that regenerates an assistant message.
```tsx
[Retry]
```
ActionBarFeedbackPositive / ActionBarFeedbackNegative \[#actionbarfeedbackpositive--actionbarfeedbacknegative]
Pressable buttons for submitting message feedback.
```tsx
{({ isSubmitted }) => {isSubmitted ? "[Liked]" : "[Like]"}}
{({ isSubmitted }) => {isSubmitted ? "[Disliked]" : "[Dislike]"}}
```
BranchPicker \[#branchpicker]
```tsx
import {
BranchPickerPrevious,
BranchPickerNext,
BranchPickerNumber,
BranchPickerCount,
} from "@assistant-ui/react-ink";
```
BranchPickerPrevious / BranchPickerNext \[#branchpickerprevious--branchpickernext]
Pressable buttons to navigate between message branches.
```tsx
{"<"}
/
{">"}
```
BranchPickerNumber / BranchPickerCount \[#branchpickernumber--branchpickercount]
`Text` components displaying the current branch number and total count.
ThreadList \[#threadlist]
```tsx
import {
ThreadListRoot,
ThreadListItems,
ThreadListNew,
} from "@assistant-ui/react-ink";
```
ThreadListRoot \[#threadlistroot]
Container `Box` for the thread list.
ThreadListItems \[#threadlistitems]
Renders thread list items with runtime integration.
```tsx
(
)}
/>
```
| Prop | Type | Description |
| ------------ | -------------------------------------------------------------- | -------------------- |
| `renderItem` | `(props: { threadId: string; index: number }) => ReactElement` | Thread item renderer |
ThreadListNew \[#threadlistnew]
Pressable that creates a new thread.
```tsx
[New Chat]
```
ThreadListItem \[#threadlistitem]
```tsx
import {
ThreadListItemRoot,
ThreadListItemTrigger,
ThreadListItemDelete,
ThreadListItemArchive,
ThreadListItemUnarchive,
} from "@assistant-ui/react-ink";
```
ThreadListItemRoot \[#threadlistitemroot]
Container `Box` for a thread list item.
ThreadListItemTrigger \[#threadlistitemtrigger]
Pressable that switches to the thread.
ThreadListItemDelete \[#threadlistitemdelete]
Pressable that deletes the thread.
ThreadListItemArchive / ThreadListItemUnarchive \[#threadlistitemarchive--threadlistitemunarchive]
Pressable buttons that archive or unarchive the thread.
```tsx
Chat #1
[x]
```
Suggestion \[#suggestion]
```tsx
import {
SuggestionTitle,
SuggestionDescription,
SuggestionTrigger,
} from "@assistant-ui/react-ink";
```
SuggestionTitle \[#suggestiontitle]
`Text` component displaying the suggestion title.
SuggestionDescription \[#suggestiondescription]
`Text` component displaying the suggestion description.
SuggestionTrigger \[#suggestiontrigger]
Pressable that triggers the suggestion action.
```tsx
```
| Prop | Type | Description |
| --------------- | --------- | --------------------------------------------------------------- |
| `send` | `boolean` | When true, sends immediately; when false, inserts into composer |
| `clearComposer` | `boolean` | Whether to clear/replace composer text (default: true) |
ChainOfThought \[#chainofthought]
```tsx
import {
ChainOfThoughtRoot,
ChainOfThoughtAccordionTrigger,
} from "@assistant-ui/react-ink";
```
ChainOfThoughtRoot \[#chainofthoughtroot]
Container `Box` for chain of thought content.
ChainOfThoughtAccordionTrigger \[#chainofthoughtaccordiontrigger]
Pressable that toggles the collapsed state of the chain of thought.
```tsx
[Toggle reasoning]
{/* reasoning content */}
```
ToolFallback \[#toolfallback]
```tsx
import { ToolFallback } from "@assistant-ui/react-ink";
```
A built-in component for rendering tool calls with expandable/collapsible output. Includes spinner for running tools and formatted JSON output.
```tsx
}
/>
```