This is beta documentation for Stream Chat React SDK v14. For the latest stable version, see the latest version (v13) .

Autocomplete Suggestions

Message input supports autocompletion for mentions, commands, and emojis.

Autocomplete suggestions are triggered by typing:

TriggerActionExample
@mention@tom
/command/giphy
:emoji:smiling

Best Practices

  • Keep suggestion lists keyboard accessible and preserve the default focus behavior.
  • Use SuggestionList and defaultComponents as the starting point for custom list UI.
  • Override the list through WithComponents so every nested composer stays consistent.
  • Keep custom suggestion item rendering lightweight.
  • Prefer using TextareaComposer inside custom inputs instead of rebuilding autocomplete behavior from scratch.

Customizing Suggestion Items

The default list implementation is SuggestionList. The simplest way to customize item rendering is to wrap it and replace one or more suggestionItemComponents.

import { SearchIndex } from "emoji-mart";
import {
  Avatar,
  Channel,
  MessageInput,
  SuggestionList,
  type SuggestionListItemComponentProps,
  type SuggestionListProps,
  defaultComponents,
  WithComponents,
} from "stream-chat-react";

const MentionItem = ({
  entity,
  focused,
  ...buttonProps
}: SuggestionListItemComponentProps) => {
  const user = entity as {
    id?: string;
    image?: string;
    name?: string;
  };

  const title = user.name ?? user.id;
  if (!title) return null;

  return (
    <button
      {...buttonProps}
      className={`suggestion-list__item ${focused ? "suggestion-list__item--selected" : ""}`}
    >
      <Avatar imageUrl={user.image} size={32} userName={title} />
      <span>{title}</span>
    </button>
  );
};

const CustomSuggestionList = (props: SuggestionListProps) => (
  <SuggestionList
    {...props}
    suggestionItemComponents={{
      ...defaultComponents,
      "@": MentionItem,
    }}
  />
);

const App = () => (
  <WithComponents
    overrides={{
      AutocompleteSuggestionList: CustomSuggestionList,
      emojiSearchIndex: SearchIndex,
    }}
  >
    <Channel>
      <MessageInput />
    </Channel>
  </WithComponents>
);
.suggestion-list__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px;
  border: 0;
  background: none;
  font: inherit;
}

.suggestion-list__item--selected {
  background: #00000014;
}

Wrapping The Default Suggestion List

If you only need extra framing around the list, keep the default list behavior and wrap SuggestionList:

import { SuggestionList, type SuggestionListProps } from "stream-chat-react";

const SuggestionListWithHeader = (props: SuggestionListProps) => (
  <div className="suggestion-list-shell">
    <div className="suggestion-list-shell__header">Suggestions</div>
    <SuggestionList {...props} />
  </div>
);

Register it with WithComponents the same way:

<WithComponents
  overrides={{ AutocompleteSuggestionList: SuggestionListWithHeader }}
>
  <Channel>
    <MessageInput />
  </Channel>
</WithComponents>

Replacing AutocompleteSuggestionItem

If you need to replace the selection wrapper itself, override AutocompleteSuggestionItem.

The current item wrapper receives SuggestionItemProps, which include:

  • item
  • focused
  • component
  • the button props passed through to the rendered item
import {
  SuggestionListItem,
  type SuggestionItemProps,
} from "stream-chat-react";

const CustomAutocompleteSuggestionItem = (props: SuggestionItemProps) => (
  <SuggestionListItem
    {...props}
    className="custom-autocomplete-suggestion-item"
  />
);

For most apps, overriding AutocompleteSuggestionList and using suggestionItemComponents is enough. Reach for AutocompleteSuggestionItem only when you want to change the shared keyboard and selection wrapper.

Custom Inputs

If you build a custom input layout, keep TextareaComposer in the tree and override the suggestion list through WithComponents. That preserves the SDK text composer, keyboard navigation, and suggestion positioning logic.

For a full custom input example, see the Input UI cookbook.