logoassistant-ui
Radix UI Primitives

ComposerPrimitive

Primitives for the text input, send button, and attachments.

The user interface to add new messages or edit existing ones.

Dual Use! A Composer placed directly inside a Thread will compose new messages. A Composer placed inside a Message will edit that message.

Anatomy

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

// creating a new message
const Composer = () => (
  <ComposerPrimitive.Root>
    <ComposerPrimitive.Attachments />
    <ComposerPrimitive.AddAttachment />
    <ComposerPrimitive.Input />
    <ComposerPrimitive.Send />
  </ComposerPrimitive.Root>
);

// editing an existing message
const EditComposer = () => (
  <ComposerPrimitive.Root>
    <ComposerPrimitive.Input />
    <ComposerPrimitive.Send />
    <ComposerPrimitive.Cancel />
  </ComposerPrimitive.Root>
);

// with voice input (dictation)
const ComposerWithDictation = () => (
  <ComposerPrimitive.Root>
    <ComposerPrimitive.Input />
    <ComposerPrimitive.If dictation={false}>
      <ComposerPrimitive.Dictate />
    </ComposerPrimitive.If>
    <ComposerPrimitive.If dictation>
      <ComposerPrimitive.StopDictation />
    </ComposerPrimitive.If>
    <ComposerPrimitive.Send />
  </ComposerPrimitive.Root>
);

API Reference

Root

Containts all parts of the composer.

This primitive renders a <form> element unless asChild is set.

ComposerRootProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

Input

The text input field for the user to type a new message.

This primitive renders a <textarea> element unless asChild is set.

ComposerPrimitiveInputProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

Keyboard Shortcuts

KeyDescription
Enter
Sends the message.
Escape
Sends a cancel action.

Send

The button to send the message.

This primitive renders a <button> element unless asChild is set.

ComposerPrimitiveSendProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

multiple:

boolean | undefined = true

Allow selecting multiple attachments at the same time.

Cancel

Sends a cancel action.

In edit composers, this action exits the edit mode.
In thread composers, this action stops the current run.

This primitive renders a <button> element unless asChild is set.

ComposerPrimitiveCancelProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

Attachments

Renders attachments. This primitive renders a separate component for each attachment.

ComposerPrimitiveAttachmentsProps

components?:

ComposerAttachmentsComponents

The component to render for each attachment.

ComposerPrimitiveAttachmentsProps['components']

Image?:

ComponentType

The component to render for each image attachment.

Document?:

ComponentType

The component to render for each document attachment.

File?:

ComponentType

The component to render for each file attachment.

Fallback?:

ComponentType

The component to render for each attachment type.

AttachmentByIndex

Renders a single attachment at the specified index within the composer.

<ComposerPrimitive.AttachmentByIndex
  index={0}
  components={{
    Image: MyImageAttachment,
    Document: MyDocumentAttachment
  }}
/>

ComposerPrimitive.AttachmentByIndex.Props

index:

number

The index of the attachment to render.

components?:

ComposerAttachmentsComponents

The components to render for the attachment.

AddAttachment

Renders a button to add an attachment.

This primitive renders a <button> element unless asChild is set.

ComposerPrimitiveAddAttachmentProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

Dictate

Renders a button to start dictation to convert voice to text.

Requires a DictationAdapter to be configured in the runtime.

This primitive renders a <button> element unless asChild is set.

ComposerPrimitiveDictateProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

StopDictation

Renders a button to stop the current dictation session.

Only rendered when dictation is active.

This primitive renders a <button> element unless asChild is set.

ComposerPrimitiveStopDictationProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

DictationTranscript

Renders the current interim (partial) transcript while dictation is active.

Note: By default, interim transcripts are displayed directly in the composer input (like native dictation). This component is for advanced customization when you want to display the interim transcript separately (e.g., in a different style or location).

Only renders when there is an active interim transcript (returns null otherwise).

This primitive renders a <span> element.

{/* Optional: Display interim transcript separately with custom styling */}
<ComposerPrimitive.If dictation>
  <div className="dictation-preview">
    <ComposerPrimitive.DictationTranscript className="italic text-muted" />
  </div>
</ComposerPrimitive.If>

If

Renders children if a condition is met.

UseComposerIfProps

editing?:

boolean | undefined

Render children if the message is being edited.

dictation?:

boolean | undefined

Render children if dictation is active.

<Composer.If editing>{/* rendered if message is being edited */}</Composer.If>

<Composer.If dictation>{/* rendered if dictation is active */}</Composer.If>