# ComposerPrimitive
URL: /docs/api-reference/primitives/Composer

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

***

title: ComposerPrimitive
description: Primitives for the text input, send button, and attachments.
-------------------------------------------------------------------------

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

import { ParametersTable } from "@/components/docs/tables/ParametersTable";
import { KeyboardTable } from "@/components/docs/tables/KeyboardTable";
import { Code } from "@radix-ui/themes";

<Callout>
  **Dual Use!** A Composer placed directly inside a `Thread` will compose new
  messages. A Composer placed inside a `Message` will edit that message.
</Callout>

## Anatomy

```tsx
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.

<ParametersTable
  type="ComposerRootProps"
  parameters={[
  {
    name: "asChild",
  },
]}
/>

### Input

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

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

<ParametersTable
  type="ComposerPrimitiveInputProps"
  parameters={[
  {
    name: "asChild",
  },
]}
/>

#### Keyboard Shortcuts

<KeyboardTable
  data={[
  {
    keys: ["Enter"],
    description: "Sends the message.",
  },
  {
    keys: ["Escape"],
    description: "Sends a cancel action.",
  },
]}
/>

### Send

The button to send the message.

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

<ParametersTable
  type="ComposerPrimitiveSendProps"
  parameters={[
  {
    name: "asChild",
  },
  {
    name: "multiple",
    type: "boolean | undefined",
    description: "Allow selecting multiple attachments at the same time.",
    default: "true",
  },
]}
/>

### 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.

<ParametersTable
  type="ComposerPrimitiveCancelProps"
  parameters={[
  {
    name: "asChild",
  },
]}
/>

### Attachments

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

<ParametersTable
  type="ComposerPrimitiveAttachmentsProps"
  parameters={[
  {
    name: "components",
    type: "ComposerAttachmentsComponents",
    description: "The component to render for each attachment.",
    children: [
      {
        type: "ComposerPrimitiveAttachmentsProps['components']",
        parameters: [
          {
            name: "Image",
            type: "ComponentType",
            description: "The component to render for each image attachment.",
          },
          {
            name: "Document",
            type: "ComponentType",
            description:
              "The component to render for each document attachment.",
          },
          {
            name: "File",
            type: "ComponentType",
            description: "The component to render for each file attachment.",
          },
          {
            name: "Fallback",
            type: "ComponentType",
            description: "The component to render for each attachment type.",
          },
        ],
      },
    ],
  },
]}
/>

### AttachmentByIndex

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

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

<ParametersTable
  type="ComposerPrimitive.AttachmentByIndex.Props"
  parameters={[
  {
    name: "index",
    type: "number",
    required: true,
    description: "The index of the attachment to render.",
  },
  {
    name: "components",
    type: "ComposerAttachmentsComponents",
    description: "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.

<ParametersTable
  type="ComposerPrimitiveAddAttachmentProps"
  parameters={[
  {
    name: "asChild",
  },
]}
/>

### 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.

<ParametersTable
  type="ComposerPrimitiveDictateProps"
  parameters={[
  {
    name: "asChild",
  },
]}
/>

### 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.

<ParametersTable
  type="ComposerPrimitiveStopDictationProps"
  parameters={[
  {
    name: "asChild",
  },
]}
/>

### DictationTranscript

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

<Callout type="info">
  **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).
</Callout>

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

This primitive renders a `<span>` element.

```tsx
{/* 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.

<ParametersTable
  type="UseComposerIfProps"
  parameters={[
  {
    name: "editing",
    required: false,
    type: "boolean | undefined",
    description: "Render children if the message is being edited.",
  },
  {
    name: "dictation",
    required: false,
    type: "boolean | undefined",
    description: "Render children if dictation is active.",
  },
]}
/>

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

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