diff --git a/web/chat/chat-constants.js b/web/chat/chat-constants.js
--- a/web/chat/chat-constants.js
+++ b/web/chat/chat-constants.js
@@ -22,6 +22,22 @@
   height: 38,
 };
 
+export const reactionTooltipStyle = {
+  paddingTop: 8,
+  paddingBottom: 8,
+  paddingLeft: 12,
+  paddingRight: 12,
+  rowGap: 4,
+  maxWidth: 136,
+  maxHeight: 162,
+};
+
+export const reactionSeeMoreLabel = 'See more';
+
+export const reactionSeeMoreLabelStyle = {
+  height: 18,
+};
+
 export const typeaheadStyle = {
   tooltipWidth: 296,
   tooltipMaxHeight: 268,
diff --git a/web/chat/reaction-tooltip.css b/web/chat/reaction-tooltip.css
new file mode 100644
--- /dev/null
+++ b/web/chat/reaction-tooltip.css
@@ -0,0 +1,28 @@
+div.container {
+  display: flex;
+  flex-direction: column;
+  background-color: var(--message-action-tooltip-bg);
+  border-radius: 8px;
+  margin: 4px 0;
+}
+
+div.container:hover {
+  cursor: pointer;
+}
+
+p.usernameText {
+  font-size: var(--s-font-14);
+  color: var(--tool-tip-color);
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+p.seeMoreText {
+  font-size: var(--xs-font-12);
+  color: var(--purple-link);
+  white-space: nowrap;
+}
+
+div.container:hover p.seeMoreText {
+  text-decoration: underline;
+}
diff --git a/web/chat/reaction-tooltip.react.js b/web/chat/reaction-tooltip.react.js
new file mode 100644
--- /dev/null
+++ b/web/chat/reaction-tooltip.react.js
@@ -0,0 +1,75 @@
+// @flow
+
+import * as React from 'react';
+
+import { useModalContext } from 'lib/components/modal-provider.react.js';
+import type { ReactionInfo } from 'lib/selectors/chat-selectors';
+
+import {
+  tooltipLabelStyle,
+  reactionTooltipStyle,
+  reactionSeeMoreLabel,
+  reactionSeeMoreLabelStyle,
+} from './chat-constants.js';
+import css from './reaction-tooltip.css';
+import MessageReactionsModal from '../modals/chat/message-reactions-modal.react.js';
+
+type Props = {
+  +reactions: ReactionInfo,
+  +reaction: string,
+};
+
+function ReactionTooltip(props: Props): React.Node {
+  const { reactions, reaction } = props;
+  const { pushModal, popModal } = useModalContext();
+
+  const onClickReactionTooltip = React.useCallback(
+    (event: SyntheticEvent<HTMLElement>) => {
+      event.preventDefault();
+
+      pushModal(
+        <MessageReactionsModal onClose={popModal} reactions={reactions} />,
+      );
+    },
+    [popModal, pushModal, reactions],
+  );
+
+  const usernames = React.useMemo(() => {
+    const { users } = reactions[reaction];
+
+    return users.map(user => (
+      <p
+        key={user.id}
+        className={css.usernameText}
+        style={{ height: tooltipLabelStyle.height }}
+      >
+        {user.username}
+      </p>
+    ));
+  }, [reaction, reactions]);
+
+  let seeMoreText;
+  if (usernames && usernames.length > 5) {
+    seeMoreText = (
+      <p
+        className={css.seeMoreText}
+        style={{ height: reactionSeeMoreLabelStyle.height }}
+      >
+        {reactionSeeMoreLabel}
+      </p>
+    );
+  }
+
+  return (
+    <div
+      className={css.container}
+      onClick={onClickReactionTooltip}
+      style={reactionTooltipStyle}
+    >
+      {usernames}
+      {seeMoreText}
+    </div>
+  );
+}
+
+export default ReactionTooltip;