import {
AttachmentSelector,
Channel,
MessageInput,
WithComponents,
defaultAttachmentSelectorActionSet,
} from "stream-chat-react";
import type {
AttachmentSelectorAction,
AttachmentSelectorActionProps,
AttachmentSelectorModalContentProps,
} from "stream-chat-react";
const AddEventAction = ({
closeMenu,
openModalForAction,
}: AttachmentSelectorActionProps) => (
<button
onClick={() => {
openModalForAction("addEvent");
closeMenu();
}}
>
Event
</button>
);
const AddEventModalContent = ({
close,
}: AttachmentSelectorModalContentProps) => (
<div>
<button onClick={close}>Done</button>
</div>
);
const attachmentSelectorActionSet: AttachmentSelectorAction[] = [
{
ActionButton: AddEventAction,
ModalContent: AddEventModalContent,
id: "event",
type: "addEvent",
},
...defaultAttachmentSelectorActionSet,
];
const CustomAttachmentSelector = () => (
<AttachmentSelector
attachmentSelectorActionSet={attachmentSelectorActionSet}
/>
);
const App = () => (
<WithComponents overrides={{ AttachmentSelector: CustomAttachmentSelector }}>
<Channel>
<MessageInput />
</Channel>
</WithComponents>
);Attachment Selector
Messages can include attachments, polls, location shares, and slash commands. AttachmentSelector renders the action button and the action menu for those composer features.
Best Practices
- Keep the default action set unless your product needs extra tools or a different order.
- Configure permissions and channel-type features before exposing selector actions.
- Use
WithComponentsfor shared selector overrides. - Audit nested scroll containers and set a custom portal destination when modal placement needs it.
- If you rebuild the whole composer, decide whether command selection should hide the selector the same way
MessageInputFlatdoes. - Expect the selector to hide or remove actions that are not available in the current channel, thread, or runtime upload state.
Default Behavior
The default selector can expose these actions:
uploadFilecreatePolladdLocationselectCommand
The SDK filters them at runtime:
- file upload is removed when uploads are disabled or unavailable
- poll creation is removed in threads and when polls are disabled
- location sharing is removed in threads and when shared locations are disabled
- the commands submenu appears only when the channel type has commands
If the only available action is file upload, the SDK renders SimpleAttachmentSelector automatically.
The selector button is also disabled while slow-mode cooldown is active.
MessageInputFlat also hides the selector while a slash command is selected. That is composer-layout behavior rather than AttachmentSelector behavior, so custom input UIs can opt in or out.
Enabling Features
The default action set depends on:
- role permissions
- channel-type configuration
- runtime upload availability from the current composer
Custom Action Sets
Customize the action menu with attachmentSelectorActionSet and register the selector through WithComponents.
Each AttachmentSelectorAction can define:
| Field | Purpose |
|---|---|
ActionButton | menu item UI |
id | stable identifier for custom actions |
ModalContent | modal content rendered after selection |
Header | submenu header component |
Submenu | submenu contents |
type | action type used by the selector runtime |
The built-in selectCommand action uses the submenu fields rather than modal content.
Poll And Location Dialogs
The selector uses PollCreationDialog and ShareLocationDialog for its default modal actions. Both are shared overrides from ComponentContext, so customize them with WithComponents:
import { Channel, MessageInput, WithComponents } from "stream-chat-react";
const CustomPollCreationDialog = ({ close }) => (
<div>
<button onClick={close}>Close poll dialog</button>
</div>
);
const CustomShareLocationDialog = ({ close }) => (
<div>
<button onClick={close}>Close location dialog</button>
</div>
);
const App = () => (
<WithComponents
overrides={{
PollCreationDialog: CustomPollCreationDialog,
ShareLocationDialog: CustomShareLocationDialog,
}}
>
<Channel>
<MessageInput />
</Channel>
</WithComponents>
);Custom Modal Portal Destination
By default, selector modals are portaled to the channel container. Use getModalPortalDestination when your layout needs a different portal root.
import { AttachmentSelector } from "stream-chat-react";
const getModalPortalDestination = () =>
document.querySelector<HTMLElement>("#my-modal-root");
const CustomAttachmentSelector = () => (
<AttachmentSelector getModalPortalDestination={getModalPortalDestination} />
);AttachmentSelectorContext
Children rendered inside AttachmentSelector can access AttachmentSelectorContext.
| Value | Description | Type |
|---|---|---|
fileInput | Reference to the hidden file input used for uploads. It is null when file uploads are unavailable. | HTMLInputElement | null |