> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-skills-v5-temp.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Composer

> Configure CometChat Flutter UI Kit Message Composer for text, media, custom messages, live reactions, editing, rich text, and audio.

<Accordion title="AI Integration Quick Reference">
  | Field                        | Value                                                                                                                                                                                                          |
  | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | Component                    | `CometChatMessageComposer`                                                                                                                                                                                     |
  | Package                      | `cometchat_chat_uikit`                                                                                                                                                                                         |
  | Import                       | `import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';`                                                                                                                                             |
  | Purpose                      | Configure CometChat Flutter UI Kit Message Composer for text, media, custom messages, live reactions, editing, rich text, and audio.                                                                           |
  | Data props                   | `user` · `group` · `parentMessageId`                                                                                                                                                                           |
  | Actions                      | `onChange` · `onError` · `onSendButtonTap` · `onRichTextFormatApplied` · `onKeyboardDiagnostics` · `onAttachmentTrayAdd` · `onAttachmentTraySend` · `onAttachmentErrorTap`                                     |
  | View slots                   | `auxiliaryButtonView` · `headerView` · `footerView` · `secondaryButtonView` · `richTextToolbarView` · `attachmentErrorSnackBarBuilder`                                                                         |
  | Styling                      | `messageComposerStyle` — the app `ThemeData` does not reach inside a kit widget, so scope colours here.                                                                                                        |
  | Sending outside the composer | A message sent with `CometChat.send*Message` instead of through this widget must emit `CometChatMessageEvents.ccMessageSent(...)` in `onSuccess`, or an already-mounted `CometChatMessageList` never shows it. |
  | Stitching                    | Pair with `CometChatMessageHeader` and `CometChatMessageList`, passing the same `user` or `group` to all three.                                                                                                |
  | Prerequisites                | `CometChatUIKit` initialised and a user logged in.                                                                                                                                                             |
  | Full props                   | [73 props](#message-composer-properties)                                                                                                                                                                       |
</Accordion>

## Overview

`CometChatMessageComposer` is a [Widget](/ui-kit/flutter/components-overview#widget) that enables users to write and send a variety of messages, including text, image, video, and custom messages.

Features such as **Live Reaction**, **Attachments**, **Message Editing**, **Rich Text Formatting**, **Code Blocks**, and **Inline Audio Recording** are supported.

`CometChatMessageComposer` is comprised of the following Base Widgets:

| Base Widgets | Description                                                                 |
| ------------ | --------------------------------------------------------------------------- |
| MessageInput | Provides a basic layout for the contents, such as the TextField and buttons |
| ActionSheet  | Presents a list of options in either a list or grid mode                    |

In V6, the composer is powered by `MessageComposerBloc` and decomposed into focused sub-widgets.

## Usage

### Integration

##### 1. Using Navigator to Launch `CometChatMessageComposer`

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    Navigator.push(context, MaterialPageRoute(builder: (context) => CometChatMessageComposer(user: user)));
    ```
  </Tab>
</Tabs>

##### 2. Embedding `CometChatMessageComposer` as a Widget in the build Method

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
    import 'package:flutter/material.dart';

    class MessageComposerScreen extends StatefulWidget {
      const MessageComposerScreen({super.key});

      @override
      State<MessageComposerScreen> createState() => _MessageComposerScreenState();
    }

    class _MessageComposerScreenState extends State<MessageComposerScreen> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            children: [
              Expanded(child: CometChatMessageList(user: user)),
              CometChatMessageComposer(user: user),
            ],
          ),
        );
      }
    }
    ```
  </Tab>
</Tabs>

***

### Actions

##### 1. OnSendButtonClick

The `OnSendButtonClick` event gets activated when the send message button is clicked.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      onSendButtonTap: (BuildContext context, BaseMessage baseMessage, PreviewMessageMode? previewMessageMode) {
        // Handle send
      },
    )
    ```
  </Tab>
</Tabs>

***

##### 2. onChange

Handles changes in the value of text in the input field.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      onChange: (String? text) {
        // Handle text change
      },
    )
    ```
  </Tab>
</Tabs>

***

##### 3. onError

Listens for any errors that occur.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      onError: (e) {
        // Handle error
      },
    )
    ```
  </Tab>
</Tabs>

***

### Filters

`CometChatMessageComposer` widget does not have any available filters.

***

### Events

The `CometChatMessageComposer` Widget does not emit any events of its own.

***

## Customization

### Style

##### 1. CometChatMessageComposerStyle

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      messageComposerStyle: CometChatMessageComposerStyle(
        sendButtonIconBackgroundColor: Color(0xFFF76808),
        secondaryButtonIconColor: Color(0xFFF76808),
        auxiliaryButtonIconColor: Color(0xFFF76808),
      ),
    )
    ```
  </Tab>
</Tabs>

##### 2. MediaRecorder Style

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      messageComposerStyle: CometChatMessageComposerStyle(
        mediaRecorderStyle: CometChatMediaRecorderStyle(
          recordIndicatorBackgroundColor: Color(0xFFF44649),
          recordIndicatorBorderRadius: BorderRadius.circular(20),
        ),
      ),
    )
    ```
  </Tab>
</Tabs>

***

### Functionality

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      placeholderText: "Type a message...",
      disableMentions: true,
    )
    ```
  </Tab>
</Tabs>

## Message Composer Properties

| Property                            | Type                                                                                              | Default                              | Description                                                                                                                                                                                                                                                                               |
| ----------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `user`                              | `User?`                                                                                           | `null`                               | Sets user for the message composer.                                                                                                                                                                                                                                                       |
| `group`                             | `Group?`                                                                                          | `null`                               | Sets group for the message composer.                                                                                                                                                                                                                                                      |
| `messageComposerStyle`              | `CometChatMessageComposerStyle?`                                                                  | `null`                               | Sets style for the message composer.                                                                                                                                                                                                                                                      |
| `placeholderText`                   | `String?`                                                                                         | `null`                               | Hint text for the input field.                                                                                                                                                                                                                                                            |
| `disableTypingEvents`               | `bool`                                                                                            | `false`                              | Disables typing events.                                                                                                                                                                                                                                                                   |
| `disableSoundForMessages`           | `bool`                                                                                            | `false`                              | Disables sound for sent messages.                                                                                                                                                                                                                                                         |
| `parentMessageId`                   | `int`                                                                                             | `0`                                  | ID of the parent message (default is 0).                                                                                                                                                                                                                                                  |
| `customSoundForMessage`             | `String?`                                                                                         | `null`                               | `customSoundForMessage` provides custom sound for message sent                                                                                                                                                                                                                            |
| `customSoundForMessagePackage`      | `String?`                                                                                         | `null`                               | `customSoundForMessagePackage` package name to show icon from                                                                                                                                                                                                                             |
| `auxiliaryButtonView`               | `ComposerWidgetBuilder?`                                                                          | `null`                               | UI component as auxiliary button.                                                                                                                                                                                                                                                         |
| `headerView`                        | `ComposerWidgetBuilder?`                                                                          | `null`                               | `headerView` ui component to be forwarded to message input component                                                                                                                                                                                                                      |
| `footerView`                        | `ComposerWidgetBuilder?`                                                                          | `null`                               | `footerView` ui component to be forwarded to message input component                                                                                                                                                                                                                      |
| `secondaryButtonView`               | `ComposerWidgetBuilder?`                                                                          | `null`                               | UI component as secondary button.                                                                                                                                                                                                                                                         |
| `sendButtonView`                    | `Widget?`                                                                                         | `null`                               | Custom send button widget.                                                                                                                                                                                                                                                                |
| `attachmentOptions`                 | `ComposerActionsBuilder?`                                                                         | `null`                               | Provides options for file attachments.                                                                                                                                                                                                                                                    |
| `text`                              | `String?`                                                                                         | `null`                               | Initial text for the input field.                                                                                                                                                                                                                                                         |
| `onChange`                          | `Function(String text)?`                                                                          | `null`                               | Callback triggered when text changes.                                                                                                                                                                                                                                                     |
| `maxLine`                           | `int?`                                                                                            | `null`                               | Maximum number of lines allowed.                                                                                                                                                                                                                                                          |
| `auxiliaryButtonsAlignment`         | `AuxiliaryButtonsAlignment?`                                                                      | `null`                               | `auxiliaryButtonsAlignment` controls position auxiliary button view                                                                                                                                                                                                                       |
| `attachmentIconURL`                 | `String?`                                                                                         | `null`                               | `attachmentIconURL` path of the icon to show in the attachments button                                                                                                                                                                                                                    |
| `stateCallBack`                     | `void Function(MessageComposerBloc bloc)?`                                                        | `null`                               | `stateCallBack` callback to handle state of the message composer Now returns MessageComposerBloc instead of the old controller                                                                                                                                                            |
| `attachmentIcon`                    | `Widget?`                                                                                         | `null`                               | Custom attachment icon.                                                                                                                                                                                                                                                                   |
| `onError`                           | `OnError?`                                                                                        | `null`                               | Callback to handle errors.                                                                                                                                                                                                                                                                |
| `onSendButtonTap`                   | `Function( BuildContext context, BaseMessage message, PreviewMessageMode? previewMessageMode, )?` | `null`                               | Callback when send button is tapped.                                                                                                                                                                                                                                                      |
| `hideVoiceRecordingButton`          | `bool?`                                                                                           | `null`                               | Hide the voice recording button.                                                                                                                                                                                                                                                          |
| `useInlineAudioRecorder`            | `bool`                                                                                            | `true`                               | `useInlineAudioRecorder` when true, shows inline audio recorder in the composer instead of opening a bottom sheet.                                                                                                                                                                        |
| `voiceRecordingIcon`                | `Widget?`                                                                                         | `null`                               | Custom voice recording icon.                                                                                                                                                                                                                                                              |
| `aiIcon`                            | `Widget?`                                                                                         | `null`                               | `attachmentIcon` custom ai icon                                                                                                                                                                                                                                                           |
| `aiIconURL`                         | `String?`                                                                                         | `null`                               | `aiIconURL` path of the icon to show in the ai button                                                                                                                                                                                                                                     |
| `aiIconPackageName`                 | `String?`                                                                                         | `null`                               | `aiIconPackageName` package name to show icon from                                                                                                                                                                                                                                        |
| `textFormatters`                    | `List<CometChatTextFormatter>?`                                                                   | `null`                               | `textFormatters` provides list of text formatters                                                                                                                                                                                                                                         |
| `disableMentions`                   | `bool?`                                                                                           | `null`                               | Disables mentions in the composer.                                                                                                                                                                                                                                                        |
| `textEditingController`             | `TextEditingController?`                                                                          | `null`                               | Controls the state of the text field.                                                                                                                                                                                                                                                     |
| `padding`                           | `EdgeInsetsGeometry?`                                                                             | `null`                               | `padding` provides padding to the message composer                                                                                                                                                                                                                                        |
| `messageInputPadding`               | `EdgeInsetsGeometry?`                                                                             | `null`                               | `messageInputPadding` sets the padding to the message input field                                                                                                                                                                                                                         |
| `recorderStartButtonIcon`           | `Widget?`                                                                                         | `null`                               | `recorderStartButtonIcon` defines the icon of the start button.                                                                                                                                                                                                                           |
| `recorderPauseButtonIcon`           | `Widget?`                                                                                         | `null`                               | `recorderPauseButtonIcon` defines the icon of the pause button.                                                                                                                                                                                                                           |
| `recorderDeleteButtonIcon`          | `Widget?`                                                                                         | `null`                               | `recorderDeleteButtonIcon` defines the icon of the delete button.                                                                                                                                                                                                                         |
| `recorderStopButtonIcon`            | `Widget?`                                                                                         | `null`                               | `recorderStopButtonIcon` defines the icon of the stop button.                                                                                                                                                                                                                             |
| `recorderSendButtonIcon`            | `Widget?`                                                                                         | `null`                               | `recorderSendButtonIcon` defines the icon of the send button.                                                                                                                                                                                                                             |
| `hideSendButton`                    | `bool?`                                                                                           | `null`                               | Hide/display the send button.                                                                                                                                                                                                                                                             |
| `hideAttachmentButton`              | `bool?`                                                                                           | `null`                               | Hide/display attachment button.                                                                                                                                                                                                                                                           |
| `hideStickersButton`                | `bool?`                                                                                           | `null`                               | Hide/display the sticker button.                                                                                                                                                                                                                                                          |
| `hideAudioAttachmentOption`         | `bool?`                                                                                           | `null`                               | Hide/display audio attachment option.                                                                                                                                                                                                                                                     |
| `hideFileAttachmentOption`          | `bool?`                                                                                           | `null`                               | Hide/display file attachment option.                                                                                                                                                                                                                                                      |
| `hideImageAttachmentOption`         | `bool?`                                                                                           | `null`                               | Hide/display image attachment option.                                                                                                                                                                                                                                                     |
| `hideVideoAttachmentOption`         | `bool?`                                                                                           | `null`                               | Hide/display video attachment option.                                                                                                                                                                                                                                                     |
| `hidePollsOption`                   | `bool?`                                                                                           | `null`                               | Hide/display polls option.                                                                                                                                                                                                                                                                |
| `hideCollaborativeDocumentOption`   | `bool?`                                                                                           | `null`                               | `hideCollaborativeDocumentOption` is a `bool` that can be used to hide/display collaborative document option                                                                                                                                                                              |
| `hideCollaborativeWhiteboardOption` | `bool?`                                                                                           | `null`                               | `hideCollaborativeWhiteboardOption` is a `bool` that can be used to hide/display collaborative whiteboard option                                                                                                                                                                          |
| `hideTakePhotoOption`               | `bool?`                                                                                           | `null`                               | `hideTakePhotoOption` is a `bool` that can be used to hide/display take photo option                                                                                                                                                                                                      |
| `sendButtonIcon`                    | `Widget?`                                                                                         | `null`                               | Custom send button icon.                                                                                                                                                                                                                                                                  |
| `disableMentionAll`                 | `bool`                                                                                            | `false`                              | `disableMentionAll` is a boolean which is used to disable @all mentions in groups                                                                                                                                                                                                         |
| `mentionAllLabel`                   | `String?`                                                                                         | `null`                               | `mentionAllLabel` is a String which is used to set a custom label for @all mentions                                                                                                                                                                                                       |
| `mentionAllLabelId`                 | `String?`                                                                                         | `null`                               | `mentionAllLabelId` is a String which is used to set a custom label ID for @all mentions                                                                                                                                                                                                  |
| `enableRichTextFormatting`          | `bool`                                                                                            | `true`                               | Master switch for rich text (markdown detection, toolbar, WYSIWYG rendering). Default `true`.                                                                                                                                                                                             |
| `showRichTextFormattingOptions`     | `bool`                                                                                            | `true`                               | Whether the rich text toolbar UI is visible. Default `true`.                                                                                                                                                                                                                              |
| `hideRichTextFormattingOptions`     | `Set<FormatType>`                                                                                 | `const {}`                           | Set of format buttons to hide from the toolbar. Default `{}`.                                                                                                                                                                                                                             |
| `richTextToolbarView`               | `Widget Function(BuildContext context, TextEditingController controller)?`                        | `null`                               | Custom rich text toolbar widget.                                                                                                                                                                                                                                                          |
| `onRichTextFormatApplied`           | `void Function(FormatType formatType)?`                                                           | `null`                               | Callback fired when a toolbar format is applied.                                                                                                                                                                                                                                          |
| `hideBottomSafeArea`                | `bool`                                                                                            | `false`                              | Hide bottom safe area padding (default: `false`).                                                                                                                                                                                                                                         |
| `resizeToAvoidBottomInset`          | `bool`                                                                                            | `true`                               | Indicates the parent `Scaffold` uses its default `resizeToAvoidBottomInset: true` and will handle keyboard insets itself. Default `true`. Flip to `false` only if you opt into the composer's internal keyboard-aware spacing and set `resizeToAvoidBottomInset: false` on your Scaffold. |
| `layout`                            | `CometChatComposerLayout`                                                                         | `CometChatComposerLayout.singleLine` | Composer skeleton: `singleLine` (default) or `doubleLine`. See [Layout](#layout) below.                                                                                                                                                                                                   |
| `onKeyboardDiagnostics`             | `CometChatKeyboardDiagnosticsCallback?`                                                           | `null`                               | Debug hook fired on every internal keyboard-state change. Leave `null` in production.                                                                                                                                                                                                     |
| `enableMultipleAttachments`         | `bool`                                                                                            | `true`                               | `enableMultipleAttachments` when true (the default) the composer owns a multi-attachment staging tray: picked files upload immediately, stage as tray tiles, and send as one message per…                                                                                                 |
| `attachmentTrayController`          | `AttachmentTrayController?`                                                                       | `null`                               | Optional external staging tray controller.                                                                                                                                                                                                                                                |
| `onAttachmentTrayAdd`               | `VoidCallback?`                                                                                   | `null`                               | Invoked by the tray's Add affordance when `attachmentTrayController` is set.                                                                                                                                                                                                              |
| `onAttachmentTraySend`              | `VoidCallback?`                                                                                   | `null`                               | Invoked by the tray's Send affordance (shown only when the tray can send).                                                                                                                                                                                                                |
| `disableImagePaste`                 | `bool`                                                                                            | `false`                              | `disableImagePaste` disables staging an image pasted from the clipboard (context-menu Paste, Cmd/Ctrl+V, and the web paste event).                                                                                                                                                        |
| `disableDragAndDrop`                | `bool`                                                                                            | `false`                              | `disableDragAndDrop` disables staging files dragged onto the chat and the "drop files here" overlay (web only).                                                                                                                                                                           |
| `attachmentErrorAlertStyle`         | `CometChatAttachmentErrorAlertStyle?`                                                             | `null`                               | `attachmentErrorAlertStyle` styles every attachment error alert: the toast shown when a selection is over the count/size limit, and the alert stating why a staged attachment was rejected…                                                                                               |
| `attachmentErrorSnackBarBuilder`    | `SnackBar Function(BuildContext context, AttachmentTile tile)?`                                   | `null`                               | `attachmentErrorSnackBarBuilder` fully replaces the default error snackbar.                                                                                                                                                                                                               |
| `onAttachmentErrorTap`              | `void Function(BuildContext context, AttachmentTile tile)?`                                       | `null`                               | `onAttachmentErrorTap` fully overrides the tap/hover action on an errored tile (skips showing the default/custom snackbar entirely).                                                                                                                                                      |

***

### Advanced

#### TextFormatters

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      textFormatters: [
        CometChatMentionsFormatter(
          style: CometChatMentionsStyle(
            mentionSelfTextBackgroundColor: Color(0xFFF76808),
            mentionTextBackgroundColor: Colors.white,
            mentionTextColor: Colors.black,
            mentionSelfTextColor: Colors.white,
          ),
        ),
      ],
    )
    ```
  </Tab>
</Tabs>

***

#### AttachmentOptions

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      attachmentOptions: (context, user, group, id) {
        return <CometChatMessageComposerAction>[
          CometChatMessageComposerAction(
            id: "Custom Option",
            title: "Custom Option",
            icon: Icon(Icons.add_box, color: Colors.black),
          ),
        ];
      },
    )
    ```
  </Tab>
</Tabs>

***

#### AuxiliaryButton Widget

You can customize the auxiliary button area (mic, sticker, etc.) using the `auxiliaryButtonView` parameter:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      auxiliaryButtonView: (context, user, group, id) {
        return Row(
          children: [
            IconButton(
              icon: Icon(Icons.location_pin, color: Color(0xFF6852D6)),
              onPressed: () {
                // Handle location sharing
              },
            ),
          ],
        );
      },
    )
    ```
  </Tab>
</Tabs>

***

## Layout

The composer skeleton supports two layouts via the `layout` prop:

| Value                                | Description                                                                           |
| ------------------------------------ | ------------------------------------------------------------------------------------- |
| `CometChatComposerLayout.singleLine` | **Default.** Text field and all buttons share a single row.                           |
| `CometChatComposerLayout.doubleLine` | Classic v5 look — text field on its own row, buttons on a second row below a divider. |

All existing props (hide flags, view slots, style, mentions, rich text, voice recording, reply/edit preview, AI options) work identically in both layouts.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      layout: CometChatComposerLayout.doubleLine,
    )
    ```
  </Tab>
</Tabs>

***

## Rich Text Formatting

The composer ships with a WYSIWYG rich-text toolbar that parses Markdown as the user types and renders formatted spans in place. Configuration is done with three flat props.

### Enable with defaults

Rich text is on by default — no props required.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(user: user)
    ```
  </Tab>
</Tabs>

### Show or hide the toolbar UI

`showRichTextFormattingOptions` controls toolbar visibility. When `false`, markdown is still parsed in typed text but no toolbar is rendered.

| Layout       | Toolbar placement                                                      |
| ------------ | ---------------------------------------------------------------------- |
| `singleLine` | Persistent row directly below the text input                           |
| `doubleLine` | Behind an `Aa` toggle in the button row — tapping swaps in the toolbar |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      showRichTextFormattingOptions: false, // parses markdown, no toolbar
    )
    ```
  </Tab>
</Tabs>

### Hide specific format buttons

Pass a `Set<FormatType>` listing the buttons to remove from the toolbar.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      hideRichTextFormattingOptions: const {
        FormatType.strikethrough,
        FormatType.codeBlock,
        FormatType.blockquote,
      },
    )
    ```
  </Tab>
</Tabs>

### Disable rich text entirely

Set `enableRichTextFormatting: false` to behave as a plain text field — no markdown parsing, no toolbar, regardless of the other two props.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      enableRichTextFormatting: false,
    )
    ```
  </Tab>
</Tabs>

### FormatType values

| Value                      | Markdown             |
| -------------------------- | -------------------- |
| `FormatType.bold`          | `**text**`           |
| `FormatType.italic`        | `_text_` or `*text*` |
| `FormatType.underline`     | `<u>text</u>`        |
| `FormatType.strikethrough` | `~~text~~`           |
| `FormatType.inlineCode`    | `` `code` ``         |
| `FormatType.codeBlock`     | ` ```code``` `       |
| `FormatType.link`          | `[text](url)`        |
| `FormatType.bulletList`    | `- item`             |
| `FormatType.orderedList`   | `1. item`            |
| `FormatType.blockquote`    | `> quote`            |

### Custom toolbar view

`richTextToolbarView` receives the active controller. Because the controller is a `RichTextEditingController` under the hood, apply formats directly via `applyFormat`.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      richTextToolbarView: (context, controller) {
        return Row(
          children: [
            IconButton(
              icon: const Icon(Icons.format_bold),
              onPressed: () {
                (controller as RichTextEditingController).applyFormat(FormatType.bold);
              },
            ),
            IconButton(
              icon: const Icon(Icons.format_italic),
              onPressed: () {
                (controller as RichTextEditingController).applyFormat(FormatType.italic);
              },
            ),
          ],
        );
      },
      onRichTextFormatApplied: (formatType) {
        debugPrint('Applied ${formatType.name}');
      },
    )
    ```
  </Tab>
</Tabs>

***

## Multiple Attachments

The composer can stage several media/file attachments and send them as one message.

1. **Pick** — the image/video option opens a multi-select picker, capped to the slots left on the message. Audio and documents are multi-select too.
2. **Stage** — each pick lands in the **attachment tray** as a tile with a live progress ring, and starts uploading immediately.
3. **Send** — the send button stays disabled until every tile finishes. Text typed alongside rides along as the **caption**, with rich-text formatting preserved as Markdown.

Files can also arrive by **clipboard paste** (images, video, audio, documents) and, on web, by **drag-and-drop** onto the composer.

A selection spanning several kinds is split by kind and sent as one message per kind, in the order image → video → audio → file. Every message therefore carries a single kind and renders with that kind's bubble — pick three photos and a PDF and the photos still arrive as an image grid, the PDF as a file card. They share a `batchId`, so the [Message List](/ui-kit/flutter/message-list#multiple-attachments) groups them as one block.

<Note>
  Voice notes are never staged — a recording is always its own message and sends immediately. While the tray holds any tile, the mic button is hidden.
</Note>

### Limits and Validation

Limits come from your app's settings in the [CometChat dashboard](https://app.cometchat.com) and are read at runtime — the UI Kit does not hardcode them.

| Limit             | Setting                          | Behaviour                                                                                                                          |
| ----------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Files per message | `file.count.max` (default 10)    | The picker is capped to the remaining slots. A selection larger than that is rejected **whole**, with a toast — nothing is staged. |
| Per-file size     | `file.size.max` (default 100 MB) | An over-sized file becomes a non-retryable error tile stating the limit.                                                           |
| File type         | Server-side                      | Rejected uploads become error tiles.                                                                                               |

Error tiles come in two flavours and behave differently:

* **Failed** (network dropped) — tap the tile to **retry** it in place.
* **Rejected** (too large, wrong type, over the count) — not retryable; tapping explains why, and you remove the tile.

Sending is blocked while any tile is uploading **or** in error, so a caption can never go out while its attachments are still in flight.

### Disabling Multiple Attachments

Multiple attachments are on by default. Turn them off to restore the classic one-file-per-message behaviour.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      enableMultipleAttachments: false,
    )
    ```
  </Tab>
</Tabs>

<Warning>
  This is composer-side only. Incoming messages carrying several attachments still render as grouped bubbles — that is controlled by `enableMultipleAttachments` on [`CometChatMessageList`](/ui-kit/flutter/message-list#multiple-attachments).
</Warning>

### Styling the Attachment Tray

The staging tray's tiles are styled through the composer's own style object.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      messageComposerStyle: CometChatMessageComposerStyle(
        attachmentTrayStyle: CometChatAttachmentTrayStyle(),
      ),
    )
    ```
  </Tab>
</Tabs>

### Style the error alerts

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageComposer(
      user: user,
      // Styles the alert shown when a selection is over the count limit.
      attachmentErrorAlertStyle: CometChatAttachmentErrorAlertStyle(),
      // Replace the default error snackbar entirely.
      attachmentErrorSnackBarBuilder: (context, tile) => MySnackBar(tile),
      // Called when the user taps an error tile (skips the snackbar).
      onAttachmentErrorTap: (context, tile) {},
    )
    ```
  </Tab>
</Tabs>

### Multiple Attachments Properties

| Property                         | Data Type                                        | Description                                                  |
| -------------------------------- | ------------------------------------------------ | ------------------------------------------------------------ |
| `enableMultipleAttachments`      | `bool`                                           | Master switch for staging. Defaults to `true`.               |
| `attachmentTrayController`       | `AttachmentTrayController?`                      | Drive the tray yourself. When omitted the composer owns one. |
| `onAttachmentTrayAdd`            | `VoidCallback?`                                  | Fires when the user taps **+** on the tray.                  |
| `onAttachmentTraySend`           | `VoidCallback?`                                  | Overrides the batch send — you send the messages yourself.   |
| `disableImagePaste`              | `bool`                                           | Turns off clipboard paste. Defaults to `false`.              |
| `disableDragAndDrop`             | `bool`                                           | Turns off drag-and-drop on web. Defaults to `false`.         |
| `errorAlertStyle`                | `CometChatErrorAlertStyle?`                      | Styles the over-limit toast.                                 |
| `attachmentErrorSnackBarStyle`   | `CometChatAttachmentErrorSnackBarStyle?`         | Styles the error-tile snackbar.                              |
| `attachmentErrorSnackBarBuilder` | `Widget Function(BuildContext, AttachmentTile)?` | Replaces the error snackbar.                                 |
| `onAttachmentErrorTap`           | `Function(AttachmentTile)?`                      | Called when an error tile is tapped.                         |

For the upload API underneath the tray, see [Upload Files & Send Attachments](/sdk/flutter/upload-files).

***

## V6 Architecture

### Sub-Widget Decomposition

| Widget                            | Purpose                   |
| --------------------------------- | ------------------------- |
| `AttachmentOptionsOverlay`        | Attachment picker overlay |
| `MessageComposerAuxiliaryButtons` | Auxiliary button area     |
| `MessageComposerSecondaryButtons` | Secondary button area     |
| `MessageComposerSendButton`       | Send button               |
| `MessageComposerSuggestionList`   | Suggestion/mention list   |
| `ComposerAttachmentUtils`         | Attachment utilities      |

### BLoC Architecture

| Component              | Description                                                                                        |
| ---------------------- | -------------------------------------------------------------------------------------------------- |
| `MessageComposerBloc`  | Manages composer state                                                                             |
| `MessageComposerEvent` | Events: `SendTextMessage`, `SendMediaMessage`, `EditTextMessage`, `StartTyping`, `EndTyping`, etc. |
| `MessageComposerState` | Composer state                                                                                     |

### Use Cases

| Use Case                   | Description                 |
| -------------------------- | --------------------------- |
| `SendTextMessageUseCase`   | Sends text messages         |
| `SendMediaMessageUseCase`  | Sends media messages        |
| `SendCustomMessageUseCase` | Sends custom messages       |
| `EditMessageUseCase`       | Edits messages              |
| `TypingUseCases`           | Start/end typing indicators |
| `GetLoggedInUserUseCase`   | Gets the logged-in user     |
