Info:
This is release candidate documentation for Stream Chat React SDK v15. For the latest stable version, see the latest version (v14).

Attachment Selector

AttachmentSelector is the button before the composer's input. It opens a menu to upload a file, create a poll, share a location or pick a command. The menu is an action set: a list of actions, each with a type and a component. Attachments and uploads explains uploads, and Actions explains the action set.

Best practices

  • Change the menu by passing your own attachmentSelectorActionSet, built from defaultAttachmentSelectorActionSet. Register the selector that renders it under the AttachmentSelector key.
  • Decide who can upload, create polls and share locations on the server and in client.config. The selector shows only what the user can do, and that filter can't be turned off.
  • Give a custom action a type of its own. The four built-in types are filtered, whatever component you give them.
  • Set getModalPortalDestination when the selector renders outside a Channel, or when the channel's container clips its dialogs.

Default behavior

The default menu has four actions, in this order:

Type Label What it does Shown when
uploadFile File Opens the file picker Uploads are allowed and the message has room for another file
createPoll Poll Opens the poll creation dialog Polls are turned on, the user has the send-poll capability, and it's not a thread
addLocation Location Opens the location sharing dialog Location sharing is turned on, and it's not a thread
selectCommand Commands Opens a submenu of the channel's commands The channel type has commands

AttachmentSelector applies this filter itself, every time it renders, to the default set and to any set you pass. An action of any other type is always shown.

What the selector renders depends on what's left:

  • No actions: nothing.
  • Only uploadFile: SimpleAttachmentSelector, a button that opens the file picker directly. It renders only when the user has the upload-file capability, even when attachments.customCdn is true. So with a custom CDN and no upload-file, a user who can only upload sees no button at all.
  • Otherwise: the button and its menu.

The button is disabled during a slow-mode cooldown. While a command is selected, it's hidden with a CSS transition and taken out of the tab order. Inside a message, as when a message is edited where it sits, the default layout renders SimpleAttachmentSelector in its place, which checks only the upload-file capability.

Enabling features

Each action follows the settings below. Configuration explains how the server and client.config combine.

  • File: attachments.enabled in the composer configuration, the channel type's uploads setting and the user's upload-file capability. With attachments.customCdn: true, only attachments.enabled counts. The action also disappears when the message holds attachments.maxNumberOfFilesPerMessage files. See Attachments and uploads.
  • Poll: polls.enabled in the composer configuration, the channel type's polls setting and the send-poll capability. See Polls.
  • Location: location.enabled in the composer configuration and the channel type's shared_locations setting. See Location sharing.
  • Commands: the channel type's commands. See Commands and Giphy.

Custom action sets

AttachmentSelector props:

Prop Type Default Description
attachmentSelectorActionSet AttachmentSelectorAction[] defaultAttachmentSelectorActionSet The actions of the menu, top to bottom. The filter in Default behavior still applies.
buttonProps Omit<ButtonProps, "onClick"> none Props for the button that opens the menu, or for the button of SimpleAttachmentSelector.
getModalPortalDestination () => HTMLElement | null the Channel container The element the action dialogs render into. See Custom modal portal destination.

An AttachmentSelectorAction has these fields:

Field Type Description
type "uploadFile" | "createPoll" | "addLocation" | "selectCommand" | string What the action is. Also the key passed to openModalForAction.
ActionButton ComponentType<AttachmentSelectorActionProps> The menu item. It gets openModalForAction(type), and submenuItems and submenuHeader when the action has a submenu.
ModalContent ComponentType<AttachmentSelectorModalContentProps> What openModalForAction(type) opens in a modal. It gets close.
Submenu ContextMenuSubmenu A submenu, as the commands action has.
Header ContextMenuHeaderComponent The header of the submenu.
id string An identifier of your own. The selector doesn't read it.

A menu item closes the menu with closeMenu() from useContextMenuContext(). The default items are exported as DefaultAttachmentSelectorComponents: File, Poll, Location and Command.

This selector leaves out Location:

import type { PropsWithChildren } from "react";
import {
  AttachmentSelector,
  defaultAttachmentSelectorActionSet,
  WithComponents,
} from "stream-chat-react";

const actionSet = defaultAttachmentSelectorActionSet.filter(
  ({ type }) => type !== "addLocation",
);

const AttachmentSelectorWithoutLocation = () => (
  <AttachmentSelector attachmentSelectorActionSet={actionSet} />
);

const overrides = { AttachmentSelector: AttachmentSelectorWithoutLocation };

export const WithoutLocationAction = ({ children }: PropsWithChildren) => (
  <WithComponents overrides={overrides}>{children}</WithComponents>
);

Attachment selector actions adds an action of its own, and the Attachment actions recipe builds one with a dialog.

Poll and location dialogs

The createPoll and addLocation actions open the PollCreationDialog and ShareLocationDialog overrides, unless the action has a ModalContent of its own. Both dialogs get close. Opening the poll dialog starts a new poll in the composer's pollComposer.

import type { PropsWithChildren } from "react";
import type { PollCreationDialogProps } from "stream-chat-react";
import { PollCreationDialog, WithComponents } from "stream-chat-react";

const PollDialogWithIntro = (props: PollCreationDialogProps) => (
  <div className="poll-dialog">
    <p>Polls close after a week.</p>
    <PollCreationDialog {...props} />
  </div>
);

const overrides = { PollCreationDialog: PollDialogWithIntro };

export const WithPollDialogIntro = ({ children }: PropsWithChildren) => (
  <WithComponents overrides={overrides}>{children}</WithComponents>
);

The dialogs' own props are on Poll components and Location sharing.

Custom modal portal destination

The action dialogs render into the Channel container, the element with the str-chat__channel id. Outside a Channel, or when that container clips them, pass getModalPortalDestination:

import { AttachmentSelector } from "stream-chat-react";

const getModalPortalDestination = () =>
  document.getElementById("chat-modal-root");

export const AttachmentSelectorWithModalRoot = () => (
  <AttachmentSelector getModalPortalDestination={getModalPortalDestination} />
);

Register it under the AttachmentSelector key. Dialogs explains modals.

AttachmentSelectorContext

The menu items of AttachmentSelector can read AttachmentSelectorContext with useAttachmentSelectorContext():

Value Type Description
fileInput HTMLInputElement | null The hidden file input of the selector. Call fileInput.click() to open the file picker. null until the input renders, and outside the selector.

SimpleAttachmentSelector doesn't provide this context.

Hooks