logoassistant-ui
API ReferenceRadix UI Primitives

AssistantIf

Conditionally render children based on assistant state.

Anatomy

import { AssistantIf } from "@assistant-ui/react";

<AssistantIf condition={({ thread }) => thread.isEmpty}>
  <WelcomeScreen />
</AssistantIf>

Overview

AssistantIf is a generic conditional rendering component that provides access to the full assistant state. It replaces the deprecated ThreadPrimitive.If, MessagePrimitive.If, and ComposerPrimitive.If components with a single, flexible API.

API Reference

AssistantIfProps

condition:

(state: AssistantState) => boolean

A function that receives the assistant state and returns whether to render children.

children?:

ReactNode

Content to render when the condition returns true.

AssistantState

The condition function receives an AssistantState object with the following properties:

AssistantState

thread?:

ThreadState

The current thread state (always available).

message?:

MessageState

The current message state (available within a message context).

composer?:

ComposerState

The current composer state (always available).

part?:

PartState

The current message part state (available within a part context).

attachment?:

AttachmentState

The current attachment state (available within an attachment context).

Examples

Thread State Conditions

// Show welcome screen when thread is empty
<AssistantIf condition={({ thread }) => thread.isEmpty}>
  <WelcomeScreen />
</AssistantIf>

// Show loading indicator while running
<AssistantIf condition={({ thread }) => thread.isRunning}>
  <LoadingSpinner />
</AssistantIf>

// Conditional send/cancel button
<AssistantIf condition={({ thread }) => !thread.isRunning}>
  <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
</AssistantIf>
<AssistantIf condition={({ thread }) => thread.isRunning}>
  <ComposerPrimitive.Cancel>Cancel</ComposerPrimitive.Cancel>
</AssistantIf>

Message State Conditions

// Show avatar only for assistant messages
<AssistantIf condition={({ message }) => message.role === "assistant"}>
  <AssistantAvatar />
</AssistantIf>

// Show disclaimer on last message
<AssistantIf condition={({ message }) => message.isLast}>
  <Disclaimer />
</AssistantIf>

// Toggle copy icon based on copied state
<ActionBarPrimitive.Copy>
  <AssistantIf condition={({ message }) => !message.isCopied}>
    <CopyIcon />
  </AssistantIf>
  <AssistantIf condition={({ message }) => message.isCopied}>
    <CheckIcon />
  </AssistantIf>
</ActionBarPrimitive.Copy>

// Show speak/stop button based on speech state
<AssistantIf condition={({ message }) => message.speech == null}>
  <ActionBarPrimitive.Speak>
    <SpeakIcon />
  </ActionBarPrimitive.Speak>
</AssistantIf>
<AssistantIf condition={({ message }) => message.speech != null}>
  <ActionBarPrimitive.StopSpeaking>
    <StopIcon />
  </ActionBarPrimitive.StopSpeaking>
</AssistantIf>

Composer State Conditions

// Show placeholder when composer is empty
<AssistantIf condition={({ composer }) => composer.isEmpty}>
  <PlaceholderText />
</AssistantIf>

// Show attachment preview when editing
<AssistantIf condition={({ composer }) => composer.isEditing}>
  <EditingIndicator />
</AssistantIf>

Complex Conditions

// Combine multiple conditions
<AssistantIf condition={({ thread, message }) =>
  !thread.isRunning && message.role === "assistant"
}>
  <ActionBar />
</AssistantIf>

// Custom logic
<AssistantIf condition={({ thread }) =>
  thread.messages.length > 0 && !thread.isRunning
}>
  <FollowUpSuggestions />
</AssistantIf>

Type Export

You can import the AssistantIf.Condition type for typing your condition functions:

import { AssistantIf } from "@assistant-ui/react";

const isThreadEmpty: AssistantIf.Condition = ({ thread }) => thread.isEmpty;

<AssistantIf condition={isThreadEmpty}>
  <WelcomeScreen />
</AssistantIf>

Migration from Deprecated Components

ThreadPrimitive.If, MessagePrimitive.If, and ComposerPrimitive.If are deprecated. Use AssistantIf instead.

BeforeAfter
<ThreadPrimitive.If empty><AssistantIf condition={({ thread }) => thread.isEmpty}>
<ThreadPrimitive.If running><AssistantIf condition={({ thread }) => thread.isRunning}>
<ThreadPrimitive.If running={false}><AssistantIf condition={({ thread }) => !thread.isRunning}>
<MessagePrimitive.If user><AssistantIf condition={({ message }) => message.role === "user"}>
<MessagePrimitive.If assistant><AssistantIf condition={({ message }) => message.role === "assistant"}>
<MessagePrimitive.If copied><AssistantIf condition={({ message }) => message.isCopied}>
<MessagePrimitive.If speaking><AssistantIf condition={({ message }) => message.speech != null}>
<MessagePrimitive.If last><AssistantIf condition={({ message }) => message.isLast}>
<ComposerPrimitive.If editing><AssistantIf condition={({ composer }) => composer.isEditing}>