diff --git a/web/chat/chat-input-bar.react.js b/web/chat/chat-input-bar.react.js
--- a/web/chat/chat-input-bar.react.js
+++ b/web/chat/chat-input-bar.react.js
@@ -17,8 +17,9 @@
   getMentionTypeaheadUserSuggestions,
   getTypeaheadRegexMatches,
   getUserMentionsCandidates,
+  type MentionTypeaheadSuggestionItem,
+  type TypeaheadMatchedStrings,
 } from 'lib/shared/mention-utils.js';
-import type { TypeaheadMatchedStrings } from 'lib/shared/mention-utils.js';
 import { localIDPrefix, trimMessage } from 'lib/shared/message-utils.js';
 import {
   threadHasPermission,
@@ -35,7 +36,6 @@
   type ThreadInfo,
   type ClientThreadJoinRequest,
   type ThreadJoinPayload,
-  type RelativeMemberInfo,
 } from 'lib/types/thread-types.js';
 import { type UserInfos } from 'lib/types/user-types.js';
 import {
@@ -56,7 +56,11 @@
 import Multimedia from '../media/multimedia.react.js';
 import { useSelector } from '../redux/redux-utils.js';
 import { nonThreadCalendarQuery } from '../selectors/nav-selectors.js';
-import { webMentionTypeaheadRegex } from '../utils/typeahead-utils.js';
+import {
+  webMentionTypeaheadRegex,
+  getMentionTypeaheadTooltipActions,
+  getMentionTypeaheadTooltipButtons,
+} from '../utils/typeahead-utils.js';
 
 type BaseProps = {
   +threadInfo: ThreadInfo,
@@ -74,7 +78,7 @@
   +dispatchActionPromise: DispatchActionPromise,
   +joinThread: (request: ClientThreadJoinRequest) => Promise<ThreadJoinPayload>,
   +typeaheadMatchedStrings: ?TypeaheadMatchedStrings,
-  +suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>,
+  +suggestions: $ReadOnlyArray<MentionTypeaheadSuggestionItem>,
   +parentThreadInfo: ?ThreadInfo,
 };
 
@@ -364,7 +368,7 @@
     let typeaheadTooltip;
     if (
       this.props.inputState.typeaheadState.canBeVisible &&
-      this.props.suggestedUsers.length > 0 &&
+      this.props.suggestions.length > 0 &&
       this.props.typeaheadMatchedStrings &&
       this.textarea
     ) {
@@ -373,7 +377,9 @@
           inputState={this.props.inputState}
           textarea={this.textarea}
           matchedStrings={this.props.typeaheadMatchedStrings}
-          suggestedUsers={this.props.suggestedUsers}
+          suggestions={this.props.suggestions}
+          typeaheadTooltipActionsGetter={getMentionTypeaheadTooltipActions}
+          typeaheadTooltipButtonsGetter={getMentionTypeaheadTooltipButtons}
         />
       );
     }
@@ -621,23 +627,22 @@
       props.inputState.typeaheadState.keepUpdatingThreadMembers,
     ]);
 
-    const suggestedUsers: $ReadOnlyArray<RelativeMemberInfo> =
-      React.useMemo(() => {
-        if (!typeaheadMatchedStrings) {
-          return [];
-        }
-        return getMentionTypeaheadUserSuggestions(
-          userSearchIndex,
-          props.inputState.typeaheadState.frozenUserMentionsCandidates,
-          viewerID,
-          typeaheadMatchedStrings.textPrefix,
-        ).map(suggestion => suggestion.userInfo);
-      }, [
+    const suggestedUsers = React.useMemo(() => {
+      if (!typeaheadMatchedStrings) {
+        return [];
+      }
+      return getMentionTypeaheadUserSuggestions(
         userSearchIndex,
         props.inputState.typeaheadState.frozenUserMentionsCandidates,
         viewerID,
-        typeaheadMatchedStrings,
-      ]);
+        typeaheadMatchedStrings.textPrefix,
+      );
+    }, [
+      userSearchIndex,
+      props.inputState.typeaheadState.frozenUserMentionsCandidates,
+      viewerID,
+      typeaheadMatchedStrings,
+    ]);
 
     return (
       <ChatInputBar
@@ -652,7 +657,7 @@
         dispatchActionPromise={dispatchActionPromise}
         joinThread={callJoinThread}
         typeaheadMatchedStrings={typeaheadMatchedStrings}
-        suggestedUsers={suggestedUsers}
+        suggestions={suggestedUsers}
         parentThreadInfo={parentThreadInfo}
       />
     );
diff --git a/web/chat/typeahead-tooltip.react.js b/web/chat/typeahead-tooltip.react.js
--- a/web/chat/typeahead-tooltip.react.js
+++ b/web/chat/typeahead-tooltip.react.js
@@ -3,28 +3,47 @@
 import classNames from 'classnames';
 import * as React from 'react';
 
-import type { TypeaheadMatchedStrings } from 'lib/shared/mention-utils.js';
-import type { RelativeMemberInfo } from 'lib/types/thread-types.js';
+import type {
+  TypeaheadMatchedStrings,
+  TypeaheadTooltipActionItem,
+} from 'lib/shared/mention-utils.js';
 import { leastPositiveResidue } from 'lib/utils/math-utils.js';
 
 import css from './typeahead-tooltip.css';
 import type { InputState } from '../input/input-state.js';
+import type {
+  GetTypeaheadTooltipActionsParams,
+  GetMentionTypeaheadTooltipButtonsParams,
+} from '../utils/typeahead-utils.js';
 import {
   getTypeaheadOverlayScroll,
-  getTypeaheadTooltipActions,
-  getTypeaheadTooltipButtons,
   getTypeaheadTooltipPosition,
 } from '../utils/typeahead-utils.js';
 
-export type TypeaheadTooltipProps = {
+export type TypeaheadTooltipProps<SuggestionItemType> = {
   +inputState: InputState,
   +textarea: HTMLTextAreaElement,
   +matchedStrings: TypeaheadMatchedStrings,
-  +suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>,
+  +suggestions: $ReadOnlyArray<SuggestionItemType>,
+  +typeaheadTooltipActionsGetter: (
+    GetTypeaheadTooltipActionsParams<SuggestionItemType>,
+  ) => $ReadOnlyArray<TypeaheadTooltipActionItem<SuggestionItemType>>,
+  +typeaheadTooltipButtonsGetter: (
+    GetMentionTypeaheadTooltipButtonsParams<SuggestionItemType>,
+  ) => React.Node,
 };
 
-function TypeaheadTooltip(props: TypeaheadTooltipProps): React.Node {
-  const { inputState, textarea, matchedStrings, suggestedUsers } = props;
+function TypeaheadTooltip<SuggestionItemType>(
+  props: TypeaheadTooltipProps<SuggestionItemType>,
+): React.Node {
+  const {
+    inputState,
+    textarea,
+    matchedStrings,
+    suggestions,
+    typeaheadTooltipActionsGetter,
+    typeaheadTooltipButtonsGetter,
+  } = props;
 
   const { textBeforeAtSymbol, textPrefix } = matchedStrings;
 
@@ -38,7 +57,7 @@
 
   React.useEffect(() => {
     setChosenPositionInOverlay(0);
-  }, [suggestedUsers]);
+  }, [suggestions]);
 
   React.useEffect(() => {
     setIsVisibleForAnimation(true);
@@ -57,11 +76,11 @@
 
   const actions = React.useMemo(
     () =>
-      getTypeaheadTooltipActions({
+      typeaheadTooltipActionsGetter({
         inputStateDraft: inputState.draft,
         inputStateSetDraft: inputState.setDraft,
         inputStateSetTextCursorPosition: inputState.setTextCursorPosition,
-        suggestedUsers,
+        suggestions,
         textBeforeAtSymbol,
         textPrefix,
       }),
@@ -69,9 +88,10 @@
       inputState.draft,
       inputState.setDraft,
       inputState.setTextCursorPosition,
-      suggestedUsers,
+      suggestions,
       textBeforeAtSymbol,
       textPrefix,
+      typeaheadTooltipActionsGetter,
     ],
   );
 
@@ -91,12 +111,12 @@
 
   const tooltipButtons = React.useMemo(
     () =>
-      getTypeaheadTooltipButtons(
+      typeaheadTooltipButtonsGetter({
         setChosenPositionInOverlay,
         chosenPositionInOverlay,
         actions,
-      ),
-    [setChosenPositionInOverlay, actions, chosenPositionInOverlay],
+      }),
+    [typeaheadTooltipButtonsGetter, chosenPositionInOverlay, actions],
   );
 
   const close = React.useCallback(() => {
@@ -164,7 +184,7 @@
     }
   }, [chosenPositionInOverlay]);
 
-  if (suggestedUsers.length === 0) {
+  if (suggestions.length === 0) {
     return null;
   }
 
diff --git a/web/utils/typeahead-utils.js b/web/utils/typeahead-utils.js
--- a/web/utils/typeahead-utils.js
+++ b/web/utils/typeahead-utils.js
@@ -4,10 +4,13 @@
 import * as React from 'react';
 
 import { oldValidUsernameRegexString } from 'lib/shared/account-utils.js';
-import { getNewTextAndSelection } from 'lib/shared/mention-utils.js';
+import {
+  getNewTextAndSelection,
+  type MentionTypeaheadSuggestionItem,
+  type TypeaheadTooltipActionItem,
+} from 'lib/shared/mention-utils.js';
 import { stringForUserExplicit } from 'lib/shared/user-utils.js';
 import type { SetState } from 'lib/types/hook-types.js';
-import type { RelativeMemberInfo } from 'lib/types/thread-types.js';
 
 import UserAvatar from '../avatars/user-avatar.react.js';
 import { typeaheadStyle } from '../chat/chat-constants.js';
@@ -18,12 +21,6 @@
   `(?<textPrefix>(?:^(?:.|\n)*\\s+)|^)@(?<username>${oldValidUsernameRegexString})?$`,
 );
 
-export type TypeaheadTooltipAction = {
-  +key: string,
-  +execute: () => mixed,
-  +actionButtonContent: { +userID: string, +username: string },
-};
-
 export type TooltipPosition = {
   +top: number,
   +left: number,
@@ -76,55 +73,67 @@
     caretLeftOffset,
   };
 }
-export type GetTypeaheadTooltipActionsParams = {
+export type GetTypeaheadTooltipActionsParams<SuggestionItemType> = {
   +inputStateDraft: string,
   +inputStateSetDraft: (draft: string) => mixed,
   +inputStateSetTextCursorPosition: (newPosition: number) => mixed,
-  +suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>,
+  +suggestions: $ReadOnlyArray<SuggestionItemType>,
   +textBeforeAtSymbol: string,
   +textPrefix: string,
 };
 
-function getTypeaheadTooltipActions(
-  params: GetTypeaheadTooltipActionsParams,
-): $ReadOnlyArray<TypeaheadTooltipAction> {
+function getMentionTypeaheadTooltipActions(
+  params: GetTypeaheadTooltipActionsParams<MentionTypeaheadSuggestionItem>,
+): $ReadOnlyArray<TypeaheadTooltipActionItem<MentionTypeaheadSuggestionItem>> {
   const {
     inputStateDraft,
     inputStateSetDraft,
     inputStateSetTextCursorPosition,
-    suggestedUsers,
+    suggestions,
     textBeforeAtSymbol,
     textPrefix,
   } = params;
-  return suggestedUsers
-    .filter(
-      suggestedUser => stringForUserExplicit(suggestedUser) !== 'anonymous',
-    )
-    .map(suggestedUser => ({
-      key: suggestedUser.id,
-      execute: () => {
-        const { newText, newSelectionStart } = getNewTextAndSelection(
-          textBeforeAtSymbol,
-          inputStateDraft,
-          textPrefix,
-          stringForUserExplicit(suggestedUser),
-        );
-
-        inputStateSetDraft(newText);
-        inputStateSetTextCursorPosition(newSelectionStart);
-      },
-      actionButtonContent: {
-        userID: suggestedUser.id,
-        username: stringForUserExplicit(suggestedUser),
-      },
-    }));
+  const actions = [];
+  for (const suggestion of suggestions) {
+    if (suggestion.type === 'user') {
+      const suggestedUser = suggestion.userInfo;
+      if (stringForUserExplicit(suggestedUser) === 'anonymous') {
+        continue;
+      }
+      const mentionText = `@${stringForUserExplicit(suggestedUser)}`;
+      actions.push({
+        key: suggestedUser.id,
+        execute: () => {
+          const { newText, newSelectionStart } = getNewTextAndSelection(
+            textBeforeAtSymbol,
+            inputStateDraft,
+            textPrefix,
+            mentionText,
+          );
+
+          inputStateSetDraft(newText);
+          inputStateSetTextCursorPosition(newSelectionStart);
+        },
+        actionButtonContent: {
+          type: 'user',
+          userInfo: suggestedUser,
+        },
+      });
+    }
+  }
+  return actions;
 }
 
-function getTypeaheadTooltipButtons(
-  setChosenPositionInOverlay: SetState<number>,
-  chosenPositionInOverlay: number,
-  actions: $ReadOnlyArray<TypeaheadTooltipAction>,
+export type GetMentionTypeaheadTooltipButtonsParams<SuggestionItemType> = {
+  +setChosenPositionInOverlay: SetState<number>,
+  +chosenPositionInOverlay: number,
+  +actions: $ReadOnlyArray<TypeaheadTooltipActionItem<SuggestionItemType>>,
+};
+function getMentionTypeaheadTooltipButtons(
+  params: GetMentionTypeaheadTooltipButtonsParams<MentionTypeaheadSuggestionItem>,
 ): $ReadOnlyArray<React.Node> {
+  const { setChosenPositionInOverlay, chosenPositionInOverlay, actions } =
+    params;
   return actions.map((action, idx) => {
     const { key, execute, actionButtonContent } = action;
     const buttonClasses = classNames(css.suggestion, {
@@ -137,6 +146,16 @@
       setChosenPositionInOverlay(idx);
     };
 
+    let avatarComponent = null;
+    let typeaheadButtonText = null;
+    if (actionButtonContent.type === 'user') {
+      const suggestedUser = actionButtonContent.userInfo;
+      avatarComponent = (
+        <UserAvatar size="small" userID={actionButtonContent.userInfo.id} />
+      );
+      typeaheadButtonText = `@${stringForUserExplicit(suggestedUser)}`;
+    }
+
     return (
       <Button
         key={key}
@@ -144,8 +163,8 @@
         onMouseMove={onMouseMove}
         className={buttonClasses}
       >
-        <UserAvatar size="small" userID={actionButtonContent.userID} />
-        <span className={css.username}>@{actionButtonContent.username}</span>
+        {avatarComponent}
+        <span className={css.username}>{typeaheadButtonText}</span>
       </Button>
     );
   });
@@ -208,8 +227,8 @@
 export {
   webMentionTypeaheadRegex,
   getCaretOffsets,
-  getTypeaheadTooltipActions,
-  getTypeaheadTooltipButtons,
+  getMentionTypeaheadTooltipActions,
+  getMentionTypeaheadTooltipButtons,
   getTypeaheadOverlayScroll,
   getTypeaheadTooltipPosition,
 };