Primitives are thin wrappers around React Native components (View, TextInput, FlatList, Pressable) that integrate with the assistant-ui runtime. They accept all standard React Native props and add runtime-aware behavior.
Primitives are accessed via namespace imports (e.g. ThreadPrimitive.Root, ComposerPrimitive.Input), matching the pattern used in @assistant-ui/react.
Many primitives share their core logic with @assistant-ui/react via @assistant-ui/core/react. Only the UI layer (View/Pressable/Text instead of DOM elements) differs.
Thread#
import { AuiIf, ThreadPrimitive } from "@assistant-ui/react-native";
ThreadPrimitive.Root#
Container View for the thread area.
<ThreadPrimitive.Root style={{ flex: 1 }}>
{children}
</ThreadPrimitive.Root>
| Prop | Type | Description |
|---|---|---|
...rest | ViewProps | Standard React Native View props |
ThreadPrimitive.Messages#
Deprecated FlatList-based message list kept for backwards compatibility. It uses ThreadPrimitive.MessagesFlatList internally, but keeps the previous no-auto-scroll default so existing apps with custom scroll handling do not change behavior on upgrade.
Use ThreadPrimitive.MessagesFlatList for new React Native threads.
<ThreadPrimitive.Messages>
{() => <MyMessage />}
</ThreadPrimitive.Messages>
You can also provide role-specific components:
<ThreadPrimitive.Messages>
{({ message }) => {
if (message.role === "user") return <MyUserMessage />;
return <MyAssistantMessage />;
}}
</ThreadPrimitive.Messages>
| Prop | Type | Description |
|---|---|---|
children | ({ message }) => ReactNode | Render function for each message |
components | MessageComponents | Deprecated, use children. Component map: provide either a Message component (used for all roles) or role-specific UserMessage, AssistantMessage, and optionally SystemMessage. Edit composers can be set via EditComposer or role-specific variants (UserEditComposer, AssistantEditComposer, SystemEditComposer). |
...rest | ThreadPrimitive.MessagesFlatList props | Same props as ThreadPrimitive.MessagesFlatList, with the auto-scroll options defaulting to false on this deprecated wrapper |
ThreadPrimitive.MessagesFlatList#
Canonical React Native message viewport backed by FlatList. It scopes each row to its message, forwards refs to the underlying FlatList, and handles scroll-to-bottom behavior for common chat flows.
<ThreadPrimitive.MessagesFlatList autoScroll>
{() => <MyMessage />}
</ThreadPrimitive.MessagesFlatList>
| Prop | Type | Description |
|---|---|---|
children | ({ message }) => ReactNode | Render function for each message |
components | MessageComponents | Deprecated component map, use children instead |
autoScroll | boolean | Automatically keeps the list at the bottom while it is already near the bottom. Defaults to true |
scrollToBottomOnRunStart | boolean | Scrolls to the bottom when a run starts. Defaults to true |
scrollToBottomOnInitialize | boolean | Scrolls to the bottom when messages first appear. Defaults to true |
scrollToBottomOnThreadSwitch | boolean | Scrolls to the bottom when switching threads. Defaults to true |
history | { hasMore: boolean; isLoadingMore: boolean; loadMore: () => void } | Loads older messages when the list reaches its start. See Windowed History |
maintainVisibleContentPosition | FlatListProps["maintainVisibleContentPosition"] | Keeps the first visible message anchored while content is inserted above it, such as older history loading in. Defaults to { minIndexForVisible: 0 } |
...rest | FlatListProps | Standard FlatList props, except data, renderItem, and children |
The built-in auto-scroll behavior assumes the default, non-inverted FlatList direction.
ThreadPrimitive.RowsFlatList#
A FlatList over the thread flattened into rows, for long threads where one assistant message holds many parts: a row per user or system message (and per message being edited), per top-level node of an assistant message's part grouping, and per turn end. Each row renders through ThreadPrimitive.Row, so it mounts only that row's scopes, and rows keep stable keys while tokens stream and earlier pages arrive.
import { groupPartByType, ThreadPrimitive } from "@assistant-ui/react-native";
const groupBy = groupPartByType({ reasoning: ["group-reasoning"] });
<ThreadPrimitive.RowsFlatList inverted groupBy={groupBy}>
{(info) => {
switch (info.type) {
case "message":
if (info.message.composer.isEditing) return <MyEditComposer />;
return info.message.role === "system" ? (
<MySystemMessage />
) : (
<MyUserMessage />
);
case "part":
return renderPart(info.part, info.children);
case "turn-end":
return <TurnFooter row={info.row} />;
}
}}
</ThreadPrimitive.RowsFlatList>;
Keep groupBy at module scope (or in useCallback): a new function on every render rebuilds the row cache and re-renders every row.
| Prop | Type | Description |
|---|---|---|
children | (info) => ReactNode | Render function for each row, with the same contract as ThreadPrimitive.Row |
groupBy | (part, context) => readonly `group-${string}`[] | null | Coalesces adjacent assistant parts into one row, like MessagePrimitive.GroupedParts; without it every part is its own row. Keep its identity stable |
inverted | boolean | Renders the newest row at offset 0. Earlier pages load through onEndReached, and maintainVisibleContentPosition defaults to { minIndexForVisible: 0, autoscrollToTopThreshold: 4 } (without the threshold when autoScroll is false), so the visible row stays put while rows arrive and the list follows new rows while it is at the bottom. A list header at least 1pt tall, empty unless you pass ListHeaderComponent, keeps the list anchored on a newest row that renders nothing, such as a turn-end footer hidden while the reply streams |
autoScroll, scrollToBottomOnRunStart, scrollToBottomOnInitialize, scrollToBottomOnThreadSwitch | boolean | As on ThreadPrimitive.MessagesFlatList; with inverted, the bottom is offset 0 |
history | { hasMore: boolean; isLoadingMore: boolean; loadMore: () => void } | As on ThreadPrimitive.MessagesFlatList: defaults to the runtime's thread.hasEarlier paging, and loads at the start of the list, or at its end when inverted |
...rest | FlatListProps | Standard FlatList props, except data, renderItem, keyExtractor, and children |
Without inverted, it keeps the first visible row anchored with { minIndexForVisible: 0 }, exactly as ThreadPrimitive.MessagesFlatList does for messages.
ThreadPrimitive.MessageByIndex#
Renders a single message at a specific index in the thread. Provides message context so that useAuiState((s) => s.message) works inside the rendered component. This component is shared from @assistant-ui/core/react.
<ThreadPrimitive.MessageByIndex
index={0}
components={{
UserMessage: MyUserMessage,
AssistantMessage: MyAssistantMessage,
}}
/>
| Prop | Type | Description |
|---|---|---|
index | number | Zero-based index of the message to render |
components | MessageComponents | Same component map as ThreadPrimitive.Messages |
ThreadPrimitive.Empty#
Renders its children only when the thread is empty (no messages and not loading). Deprecated in favor of AuiIf.
<ThreadPrimitive.Empty>
<Text>Send a message to get started</Text>
</ThreadPrimitive.Empty>
// preferred
<AuiIf condition={(s) => s.thread.isEmpty}>
<Text>Send a message to get started</Text>
</AuiIf>
ThreadPrimitive.If#
Conditional rendering based on thread state. Deprecated in favor of AuiIf.
<ThreadPrimitive.If empty>
<Text>No messages yet</Text>
</ThreadPrimitive.If>
// preferred
<AuiIf condition={(s) => s.thread.isEmpty}>
<Text>No messages yet</Text>
</AuiIf>
<AuiIf condition={(s) => s.thread.isRunning}>
<ActivityIndicator />
</AuiIf>
| Prop | Type | Description |
|---|---|---|
empty | boolean | Renders children when thread emptiness matches this value |
running | boolean | Renders children when thread running state matches this value |
ThreadPrimitive.Suggestion#
Pressable that inserts or sends a hard-coded suggestion prompt. Unlike SuggestionPrimitive.Trigger, this component does not require a suggestion context. The prompt is passed directly as a prop.
<ThreadPrimitive.Suggestion prompt="What can you help me with?" send>
<Text>What can you help me with?</Text>
</ThreadPrimitive.Suggestion>
| Prop | Type | Description |
|---|---|---|
prompt | string | The text to send or insert into the composer |
send | boolean | When true, sends the prompt immediately; when false, inserts into composer (default: false) |
clearComposer | boolean | Whether to replace composer text (default: true) |
...rest | PressableProps | Standard Pressable props (except onPress) |
ThreadPrimitive.Suggestions#
Renders all suggestions through a children render function. This component is shared from @assistant-ui/core/react.
<ThreadPrimitive.Suggestions>
{() => <MySuggestion />}
</ThreadPrimitive.Suggestions>
| Prop | Type | Description |
|---|---|---|
children | (value: { suggestion: SuggestionState }) => ReactNode | Render function called for each suggestion |
components | { Suggestion: ComponentType } | Deprecated, use children. Component to render for each suggestion |
ThreadPrimitive.SuggestionByIndex#
Renders a single suggestion at the specified index, providing suggestion context. This component is shared from @assistant-ui/core/react.
<ThreadPrimitive.SuggestionByIndex
index={0}
components={{ Suggestion: MySuggestion }}
/>
| Prop | Type | Description |
|---|---|---|
index | number | Zero-based index of the suggestion to render |
components | { Suggestion: ComponentType } | Component to render for the suggestion |
AuiIf#
Conditional rendering based on assistant state. Replaces the deprecated ThreadPrimitive.Empty, ThreadPrimitive.If, MessagePrimitive.If, and ComposerPrimitive.If.
import { AuiIf } from "@assistant-ui/react-native";
<AuiIf condition={(s) => s.thread.isEmpty}>
<Text>Send a message to get started</Text>
</AuiIf>
<AuiIf condition={(s) => s.thread.isRunning}>
<ActivityIndicator />
</AuiIf>
| Prop | Type | Description |
|---|---|---|
condition | (state) => boolean | Selector that determines whether children are rendered |
Composer#
import {
ComposerPrimitive,
QueueItemPrimitive,
} from "@assistant-ui/react-native";
Using your own button#
Every pressable primitive accepts asChild, including the action bar, branch picker, attachment, queue item, suggestion, thread list, thread list item, and chain of thought triggers, as well as the composer controls. With it, the primitive renders its single child instead of its own Pressable and passes its press handler, disabled state, and accessibility role to that child, so a button from your UI kit becomes the press target.
<ComposerPrimitive.Send asChild>
<Button>
<Text>Send</Text>
</Button>
</ComposerPrimitive.Send>
The child's onPress runs before the primitive's action, the child's other props take precedence, styles are combined (including Pressable style functions), and refs are composed. The child must forward these props to a pressable element.
ComposerPrimitive.Root#
Container View for the composer area.
<ComposerPrimitive.Root style={styles.composerContainer}>
{children}
</ComposerPrimitive.Root>
ComposerPrimitive.Input#
TextInput wired to the composer runtime. Value and onChangeText are managed automatically.
<ComposerPrimitive.Input
placeholder="Message..."
multiline
style={styles.input}
/>
| Prop | Type | Description |
|---|---|---|
submitMode | "enter" | "none" | Whether Enter sends the message on web (default: "enter") |
...rest | TextInputProps | Standard TextInput props (except value, onChangeText) |
ComposerPrimitive.Send#
Pressable that sends the current message. Automatically disabled when the composer is empty.
<ComposerPrimitive.Send style={styles.sendButton}>
<Text>Send</Text>
</ComposerPrimitive.Send>
ComposerPrimitive.Cancel#
Pressable that cancels the current run. Automatically disabled when no run is active.
<ComposerPrimitive.Cancel style={styles.cancelButton}>
<Text>Stop</Text>
</ComposerPrimitive.Cancel>
ComposerPrimitive.Attachments#
Renders composer attachments through a children render function.
<ComposerPrimitive.Attachments>
{({ attachment }) => {
if (attachment.type === "image") return <MyImageAttachment />;
if (attachment.type === "document") return <MyDocumentAttachment />;
return <MyFallbackAttachment />;
}}
</ComposerPrimitive.Attachments>
| Prop | Type | Description |
|---|---|---|
children | (value: { attachment: Attachment }) => ReactNode | Render function called for each attachment |
components | { Image?, Document?, File?, Attachment? } | Deprecated, use children. Component renderers by attachment type |
ComposerPrimitive.AddAttachment#
Pressable for adding attachments. It is disabled while the composer cannot accept attachments. React Native has no file input, so the caller opens the platform picker (for example expo-document-picker or expo-image-picker) in onPress and passes the selection to aui.composer.addAttachment.
import { useAui } from "@assistant-ui/react-native";
import * as ImagePicker from "expo-image-picker";
import { Text } from "react-native";
const aui = useAui();
<ComposerPrimitive.AddAttachment
onPress={async () => {
const result = await ImagePicker.launchImageLibraryAsync({ base64: true });
if (result.canceled) return;
for (const asset of result.assets) {
if (!asset.base64 || !asset.mimeType) continue;
await aui.composer.addAttachment({
name: asset.fileName ?? `image.${asset.mimeType.split("/")[1]}`,
contentType: asset.mimeType,
type: "image",
content: [
{
type: "image",
image: `data:${asset.mimeType};base64,${asset.base64}`,
},
],
});
}
}}
<Text>Attach</Text>
</ComposerPrimitive.AddAttachment>
ComposerPrimitive.Queue#
Renders all queued composer items. Each item is wrapped in a QueueItemByIndexProvider, so QueueItemPrimitive.* can read item state and call queue actions inside the render prop. Backed by the shared ComposerPrimitiveQueue from @assistant-ui/core/react.
<ComposerPrimitive.Queue>
{({ queueItem }) => (
<View>
<QueueItemPrimitive.Text />
<QueueItemPrimitive.Steer>
<Text>Run now</Text>
</QueueItemPrimitive.Steer>
<QueueItemPrimitive.Remove>
<Text>Remove</Text>
</QueueItemPrimitive.Remove>
</View>
)}
</ComposerPrimitive.Queue>
| Prop | Type | Description |
|---|---|---|
children | (value: { queueItem: QueueItemState }) => ReactNode | Render function called for each queue item |
ComposerPrimitive.Quote#
Renders the active composer quote preview. Children are only rendered while s.composer.quote is set, so this acts as both a container and a gate.
<ComposerPrimitive.Quote>
<View>
<Text>Quoting:</Text>
<ComposerPrimitive.QuoteText />
<ComposerPrimitive.QuoteDismiss>
<Text>Clear</Text>
</ComposerPrimitive.QuoteDismiss>
</View>
</ComposerPrimitive.Quote>
| Prop | Type | Description |
|---|---|---|
children | ReactNode | Quote preview content; only rendered when a quote is set |
...rest | ViewProps | Standard React Native View props |
ComposerPrimitive.QuoteText#
Renders the quoted text from s.composer.quote?.text. Pass children to override the displayed value.
<ComposerPrimitive.QuoteText />
| Prop | Type | Description |
|---|---|---|
children | ReactNode | Override content; defaults to s.composer.quote?.text |
...rest | TextProps | Standard React Native Text props |
ComposerPrimitive.QuoteDismiss#
Pressable that clears the active quote by calling aui.composer.setQuote(undefined).
<ComposerPrimitive.QuoteDismiss>
<Text>Clear</Text>
</ComposerPrimitive.QuoteDismiss>
| Prop | Type | Description |
|---|---|---|
children | PressableProps["children"] | Button content, including Pressable render-function children |
...rest | Omit<PressableProps, "onPress"> | Standard React Native Pressable props except onPress |
ComposerPrimitive.AttachmentByIndex#
Renders a single composer attachment at the specified index. Useful for building custom attachment layouts.
<ComposerPrimitive.AttachmentByIndex
index={0}
components={{
Image: MyImageAttachment,
Attachment: MyFallbackAttachment,
}}
/>
| Prop | Type | Description |
|---|---|---|
index | number | Zero-based index of the attachment to render |
components | { Image?, Document?, File?, Attachment? } | Component renderers by attachment type |
Editing a message#
There are no separate edit primitives. Inside a message, the composer primitives bind to that message's edit composer, so the same ComposerPrimitive.Root, Input, Send, and Cancel build the edit UI. ActionBarPrimitive.Edit starts editing, and message.composer.isEditing tells you when to render it.
import { Text, View } from "react-native";
import {
ComposerPrimitive,
MessagePrimitive,
useAuiState,
} from "@assistant-ui/react-native";
function MessageRow() {
const isEditing = useAuiState((s) => s.message.composer.isEditing);
if (isEditing) return <EditComposer />;
return <MessageBubble />;
}
function EditComposer() {
return (
<MessagePrimitive.Root>
<ComposerPrimitive.Root style={styles.editComposer}>
<ComposerPrimitive.Input multiline autoFocus style={styles.input} />
<View style={styles.editActions}>
<ComposerPrimitive.Cancel style={styles.cancelButton}>
<Text>Cancel</Text>
</ComposerPrimitive.Cancel>
<ComposerPrimitive.Send style={styles.sendButton}>
<Text>Update</Text>
</ComposerPrimitive.Send>
</View>
</ComposerPrimitive.Root>
</MessagePrimitive.Root>
);
}
Conditional Rendering (Composer)#
Use AuiIf for conditional rendering based on composer state:
<AuiIf condition={(s) => s.composer.isEditing}>
<Text>Currently editing</Text>
</AuiIf>
<AuiIf condition={(s) => s.composer.dictation != null}>
<Text>Dictation active</Text>
</AuiIf>
Message#
import { MessagePrimitive } from "@assistant-ui/react-native";
MessagePrimitive.Root#
Container View for a single message.
<MessagePrimitive.Root style={styles.messageBubble}>
{children}
</MessagePrimitive.Root>
MessagePrimitive.Content#
Renders message content parts using render-prop functions instead of the component-map approach used by MessagePrimitive.Parts. Each part type receives a part object and its index. Registered toolkit renderers are automatically dispatched and take priority over renderToolCall.
<MessagePrimitive.Content
renderText={({ part }) => <Text>{part.text}</Text>}
renderToolCall={({ part, index }) => (
<Text>Tool: {part.toolName}</Text>
)}
renderImage={({ part }) => (
<Image source={{ uri: part.image }} />
)}
/>
| Prop | Type | Description |
|---|---|---|
renderText | (props: { part, index }) => ReactElement | Renderer for text parts (default: React Native <Text>) |
renderToolCall | (props: { part, index }) => ReactElement | Fallback renderer for tool-call parts not handled by registered tool UIs |
renderImage | (props: { part, index }) => ReactElement | Renderer for image parts (default: React Native <Image>) |
renderReasoning | (props: { part, index }) => ReactElement | Renderer for reasoning parts |
renderSource | (props: { part, index }) => ReactElement | Renderer for source parts |
renderFile | (props: { part, index }) => ReactElement | Renderer for file parts |
renderData | (props: { part, index }) => ReactElement | Fallback renderer for data parts not handled by registered data UIs |
Rendering Markdown#
MessagePrimitive.Content renders text parts with React Native's <Text> by default, so markdown syntax is displayed as plain text. To render markdown, install a React Native markdown renderer and pass it through renderText:
<InstallCommand npm={["react-native-markdown-display"]} />
import Markdown from "react-native-markdown-display";
import { MessagePrimitive } from "@assistant-ui/react-native";
const AssistantMessage = () => {
return (
<MessagePrimitive.Root>
<MessagePrimitive.Content
renderText={({ part }) => (
<Markdown>{part.text}</Markdown>
)}
/>
</MessagePrimitive.Root>
);
};
MessagePrimitive.Parts#
Renders message content parts through a children render function or a components map. Tool call and data parts automatically render registered toolkit renderers and data UIs (via useAssistantDataUI), falling back to components provided here. A default Text component using React Native's <Text> is provided out of the box.
<MessagePrimitive.Parts>
{({ part }) => {
if (part.type === "text") return <Text>{part.text}</Text>;
if (part.type === "image") return <Image source={{ uri: part.image }} />;
if (part.type === "tool-call") return <MyToolCallComponent {...part} />;
return null;
}}
</MessagePrimitive.Parts>
| Prop | Type | Description |
|---|---|---|
children | (value: { part: EnrichedPartState }) => ReactNode | Render function called for each part. Cannot be combined with components |
components | object | Component map for rendering each part type. See below. |
components fields:
| Field | Type | Description |
|---|---|---|
Text | TextMessagePartComponent | Text part renderer (default: React Native <Text>) |
Image | ImageMessagePartComponent | Image part renderer |
Reasoning | ReasoningMessagePartComponent | Reasoning part renderer |
Source | SourceMessagePartComponent | Source part renderer |
File | FileMessagePartComponent | File part renderer |
Unstable_Audio | Unstable_AudioMessagePartComponent | Audio part renderer (deprecated, render audio/* from File) |
tools | { by_name?, Fallback? } or { Override } | Tool call rendering config. Use by_name to map tool names to components, Fallback for unregistered tools, or Override to handle all tool calls |
data | { by_name?, Fallback? } | Data part rendering config. Use by_name to map data event names, Fallback for unmatched events |
Empty | EmptyMessagePartComponent | Component shown for empty messages |
Quote | QuoteMessagePartComponent | Component for rendering quoted message references |
ChainOfThought | ComponentType | Groups all reasoning and tool-call parts into a single component (mutually exclusive with Reasoning/tools/ToolGroup/ReasoningGroup) |
MessagePrimitive.PartByIndex#
Renders a single message part at the specified index, providing part context. Useful for building custom part layouts outside of MessagePrimitive.Parts. This component is shared from @assistant-ui/core/react.
<MessagePrimitive.PartByIndex
index={0}
components={{
Text: ({ text }) => <Text>{text}</Text>,
tools: { Fallback: MyToolComponent },
}}
/>
| Prop | Type | Description |
|---|---|---|
index | number | Zero-based index of the message part to render |
components | object | Same component map as MessagePrimitive.Parts |
MessagePrimitive.Quote#
Renders the quote a message was sent with, read from s.message.metadata.custom.quote. Renders nothing when the message carries no quote. Place it above MessagePrimitive.Parts in the user message. This component is shared from @assistant-ui/core/react.
<MessagePrimitive.Quote>
{({ text }) => <Text numberOfLines={2}>{text}</Text>}
</MessagePrimitive.Quote>
| Prop | Type | Description |
|---|---|---|
children | (value: { text: string; messageId: string }) => ReactNode | Render function called when the message has a quote |
Conditional Rendering (Message)#
Use AuiIf for conditional rendering based on message properties:
<AuiIf condition={(s) => s.message.role === "user"}>
<Text>You said:</Text>
</AuiIf>
<AuiIf condition={(s) => s.message.role === "assistant" && s.message.isLast}>
<ActivityIndicator />
</AuiIf>
MessagePrimitive.Attachments#
Renders user message attachments through a children render function.
<MessagePrimitive.Attachments>
{({ attachment }) => {
if (attachment.type === "image") return <MyImageAttachment />;
return <MyFallbackAttachment />;
}}
</MessagePrimitive.Attachments>
| Prop | Type | Description |
|---|---|---|
children | (value: { attachment: Attachment }) => ReactNode | Render function called for each attachment |
components | { Image?, Document?, File?, Attachment? } | Deprecated, use children. Component renderers by attachment type |
MessagePrimitive.AttachmentByIndex#
Renders a single message attachment at the specified index. Useful for building custom attachment layouts outside of MessagePrimitive.Attachments.
<MessagePrimitive.AttachmentByIndex
index={0}
components={{
Image: MyImageAttachment,
Attachment: MyFallbackAttachment,
}}
/>
| Prop | Type | Description |
|---|---|---|
index | number | Zero-based index of the attachment to render |
components | { Image?, Document?, File?, Attachment? } | Component renderers by attachment type |
Attachment#
import { AttachmentPrimitive } from "@assistant-ui/react-native";
Primitives for rendering individual attachments (inside ComposerPrimitive.Attachments or MessagePrimitive.Attachments).
AttachmentPrimitive.Root#
Container View for an attachment.
<AttachmentPrimitive.Root style={styles.attachment}>
{children}
</AttachmentPrimitive.Root>
AttachmentPrimitive.Name#
Text component displaying the attachment filename.
<AttachmentPrimitive.Name style={styles.filename} />
AttachmentPrimitive.Thumb#
Text component displaying the file extension (e.g. .pdf), or the attachment type (e.g. image) when the filename has no extension (including leading-dot names like .env). If you pass children, they override that text.
<AttachmentPrimitive.Thumb style={styles.extension} />
AttachmentPrimitive.Remove#
Pressable that removes the attachment from the composer.
<AttachmentPrimitive.Remove>
<Text>Remove</Text>
</AttachmentPrimitive.Remove>
QueueItem#
import { QueueItemPrimitive } from "@assistant-ui/react-native";
Primitives for rendering individual queued composer items. Use inside a ComposerPrimitive.Queue render prop, where the queue item context is set up by QueueItemByIndexProvider.
QueueItemPrimitive.Text#
Renders the queue item's text with React Native <Text>. Pass children to override the displayed value.
<QueueItemPrimitive.Text />
| Prop | Type | Description |
|---|---|---|
children | ReactNode | Override content; defaults to the text parts of s.queueItem.parts |
...rest | TextProps | Standard React Native Text props |
QueueItemPrimitive.Remove#
Pressable that removes the queue item by calling aui.queueItem.remove().
<QueueItemPrimitive.Remove>
<Text>Remove</Text>
</QueueItemPrimitive.Remove>
| Prop | Type | Description |
|---|---|---|
children | PressableProps["children"] | Button content, including Pressable render-function children |
...rest | Omit<PressableProps, "onPress"> | Standard React Native Pressable props except onPress |
QueueItemPrimitive.Steer#
Pressable that promotes the queue item to run next by calling aui.queueItem.steer().
<QueueItemPrimitive.Steer>
<Text>Run now</Text>
</QueueItemPrimitive.Steer>
| Prop | Type | Description |
|---|---|---|
children | PressableProps["children"] | Button content, including Pressable render-function children |
...rest | Omit<PressableProps, "onPress"> | Standard React Native Pressable props except onPress |
ActionBar#
import { ActionBarPrimitive } from "@assistant-ui/react-native";
ActionBarPrimitive.Copy#
Pressable that copies the message content. Pass a platform clipboard writer through copyToClipboard. Supports function-as-children for copy state feedback.
import * as Clipboard from "expo-clipboard";
const copyToClipboard = async (text: string) => {
const didCopy = await Clipboard.setStringAsync(text);
if (!didCopy) throw new Error("Clipboard write failed");
};
<ActionBarPrimitive.Copy
copiedDuration={3000}
copyToClipboard={copyToClipboard}
{({ isCopied }) => <Text>{isCopied ? "Copied!" : "Copy"}</Text>}
</ActionBarPrimitive.Copy>
| Prop | Type | Description |
|---|---|---|
copiedDuration | number | Duration in ms to show "copied" state (default: 3000) |
copyToClipboard | (text: string) => void | Promise<void> | Platform clipboard writer |
ActionBarPrimitive.Edit#
Pressable that enters edit mode for a message.
<ActionBarPrimitive.Edit>
<Text>Edit</Text>
</ActionBarPrimitive.Edit>
ActionBarPrimitive.Reload#
Pressable that regenerates an assistant message.
<ActionBarPrimitive.Reload>
<Text>Retry</Text>
</ActionBarPrimitive.Reload>
ActionBarPrimitive.FeedbackPositive / ActionBarPrimitive.FeedbackNegative#
Pressable buttons for submitting message feedback. The submitted one is marked for assistive technology: aria-selected on native, aria-pressed on the web.
<ActionBarPrimitive.FeedbackPositive>
{({ isSubmitted }) => <Text>{isSubmitted ? "Liked" : "Like"}</Text>}
</ActionBarPrimitive.FeedbackPositive>
<ActionBarPrimitive.FeedbackNegative>
{({ isSubmitted }) => <Text>{isSubmitted ? "Disliked" : "Dislike"}</Text>}
</ActionBarPrimitive.FeedbackNegative>
BranchPicker#
import { BranchPickerPrimitive } from "@assistant-ui/react-native";
BranchPickerPrimitive.Previous / BranchPickerPrimitive.Next#
Pressable buttons to navigate between message branches.
<View style={{ flexDirection: "row", alignItems: "center" }}>
<BranchPickerPrimitive.Previous>
<Text>-</Text>
</BranchPickerPrimitive.Previous>
<BranchPickerPrimitive.Number />
<Text>/</Text>
<BranchPickerPrimitive.Count />
<BranchPickerPrimitive.Next>
<Text>+</Text>
</BranchPickerPrimitive.Next>
</View>
BranchPickerPrimitive.Number / BranchPickerPrimitive.Count#
Text components displaying the current branch number and total count.
ThreadList#
import { ThreadListPrimitive } from "@assistant-ui/react-native";
ThreadListPrimitive.Root#
Container View for the thread list.
<ThreadListPrimitive.Root style={styles.threadList}>
{children}
</ThreadListPrimitive.Root>
ThreadListPrimitive.Items#
FlatList of thread IDs with runtime integration.
<ThreadListPrimitive.Items
renderItem={({ threadId }) => (
<ThreadListEntry threadId={threadId} />
)}
/>
| Prop | Type | Description |
|---|---|---|
renderItem | (props: { threadId: string; index: number }) => ReactElement | Thread item renderer |
...rest | FlatListProps | Standard FlatList props (except data, renderItem) |
ThreadListPrimitive.New#
Pressable that creates a new thread. While the new thread is the current one, it is marked for assistive technology: accessibilityState.selected on native, aria-current on the web.
<ThreadListPrimitive.New style={styles.newThreadButton}>
<Text>New Chat</Text>
</ThreadListPrimitive.New>
ThreadListItem#
import { ThreadListItemPrimitive } from "@assistant-ui/react-native";
Primitives for rendering individual thread list items.
ThreadListItemPrimitive.Root#
Container View for a thread list item.
<ThreadListItemPrimitive.Root style={styles.threadItem}>
{children}
</ThreadListItemPrimitive.Root>
ThreadListItemPrimitive.Title#
Renders the thread title text. Falls back to the provided fallback when title is empty. This component is shared from @assistant-ui/core/react.
<ThreadListItemPrimitive.Title fallback="New Chat" />
| Prop | Type | Description |
|---|---|---|
fallback | ReactNode | Content to show when title is empty |
ThreadListItemPrimitive.Trigger#
Pressable that switches to the thread. The current thread's trigger is marked for assistive technology: accessibilityState.selected on native, aria-current on the web.
<ThreadListItemPrimitive.Trigger>
<ThreadListItemPrimitive.Title fallback="New Chat" />
</ThreadListItemPrimitive.Trigger>
ThreadListItemPrimitive.Delete#
Pressable that deletes the thread.
<ThreadListItemPrimitive.Delete>
<Text>Delete</Text>
</ThreadListItemPrimitive.Delete>
ThreadListItemPrimitive.Archive / ThreadListItemPrimitive.Unarchive#
Pressable buttons that archive or unarchive the thread.
<ThreadListItemPrimitive.Archive>
<Text>Archive</Text>
</ThreadListItemPrimitive.Archive>
<ThreadListItemPrimitive.Unarchive>
<Text>Unarchive</Text>
</ThreadListItemPrimitive.Unarchive>
Suggestion#
import { SuggestionPrimitive } from "@assistant-ui/react-native";
Primitives for rendering suggestions. Use inside ThreadPrimitive.Suggestions or a SuggestionByIndexProvider.
SuggestionPrimitive.Title#
Text component displaying the suggestion title.
<SuggestionPrimitive.Title style={styles.suggestionTitle} />
SuggestionPrimitive.Description#
Text component displaying the suggestion description/label.
<SuggestionPrimitive.Description style={styles.suggestionDescription} />
SuggestionPrimitive.Trigger#
Pressable that triggers the suggestion action (send or insert into composer).
<SuggestionPrimitive.Trigger send>
<SuggestionPrimitive.Title />
</SuggestionPrimitive.Trigger>
| 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#
import { ChainOfThoughtPrimitive } from "@assistant-ui/react-native";
Primitives for rendering chain of thought content (grouped reasoning and tool-call parts).
ChainOfThoughtPrimitive.Root#
Container View for chain of thought content.
<ChainOfThoughtPrimitive.Root style={styles.chainOfThought}>
{children}
</ChainOfThoughtPrimitive.Root>
ChainOfThoughtPrimitive.AccordionTrigger#
Pressable that toggles the collapsed state of the chain of thought.
<ChainOfThoughtPrimitive.AccordionTrigger>
<Text>Toggle reasoning</Text>
</ChainOfThoughtPrimitive.AccordionTrigger>
ChainOfThoughtPrimitive.Parts#
Renders the parts within a chain of thought. Shared from @assistant-ui/core/react.
<ChainOfThoughtPrimitive.Parts>
{({ part }) => {
if (part.type === "reasoning") return <Text>{part.text}</Text>;
if (part.type === "tool-call") return <MyToolComponent {...part} />;
return null;
}}
</ChainOfThoughtPrimitive.Parts>