Skip to content

feat: add enhanced mentions#3189

Open
MartinCupela wants to merge 7 commits into
masterfrom
feat/enhanced-mentions
Open

feat: add enhanced mentions#3189
MartinCupela wants to merge 7 commits into
masterfrom
feat/enhanced-mentions

Conversation

@MartinCupela
Copy link
Copy Markdown
Contributor

@MartinCupela MartinCupela commented May 13, 2026

🎯 Goal

Depends on: GetStream/stream-chat-js#1743

Closes REACT-979

This PR brings enhanced mentions support to stream-chat-react across both the composer UI and rendered message text.

It updates the @ suggestion flow to render a mixed mention set from stream-chat-js, including direct users, built-in mentions like @channel and @here, roles, and user groups. The suggestion list now uses dedicated row components for each mention type, keeps keyboard navigation working across non-user items, and preserves accessibility and i18n behavior for the mixed result set.

It also extends the message text rendering pipeline so enhanced mentions are highlighted the same way direct user mentions are. The renderText path now accepts additive mention metadata, routes all mention kinds through a unified mention renderer contract via node.mentionedEntity, and keeps backward compatibility for older user-only mention consumers through the deprecated node.mentionedUser alias and the existing renderText(text, mentioned_users, options) signature.

Finally, the PR adds focused regression coverage for render-text behavior, quoted-message rendering, backward-compatible plugin usage, email-like mention edge cases, and multi-word mention names.

Highlights

  • Render mixed @ suggestion results from stream-chat-js:
    • direct users
    • @channel
    • @here
    • roles
    • user groups
  • Add dedicated suggestion row components:
    • MentionItem
    • SpecialMentionItem
    • RoleItem
    • UserGroupItem
  • Reuse a shared suggestion-row primitive for non-user mention rows
  • Preserve UserItem backward compatibility for existing consumers
  • Update suggestion-list accessibility copy for mixed mention results
  • Keep keyboard navigation and Enter selection working for non-user mentions
  • Extend renderText to support additive mention metadata through options.messageMentionEntities
  • Highlight built-in, role, and user-group mentions in:
    • message text
    • quoted messages
  • Unify rendered mention nodes under mention + node.mentionedEntity
  • Keep backward compatibility for:
    • node.mentionedUser
    • mentionsMarkdownPlugin(UserResponse[])
    • renderText(text, mentioned_users, options)

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced mention support to include channels, broadcast mentions (@here), roles, and user groups alongside user mentions
    • New ListItemLayout component for flexible, reusable list item rendering with customizable icons and content
    • New mention suggestion item components with specialized rendering for different mention types
    • Customizable Avatar fallback icons
    • Dark/inverse theme styling for buttons
  • Localization

    • Added translations for new mention types and role notification messaging across all supported languages

# Conflicts:
#	src/components/Message/__tests__/__snapshots__/MessageText.test.tsx.snap
#	src/components/Message/renderText/rehypePlugins/mentionsMarkdownPlugin.ts
#	src/components/Message/renderText/renderText.tsx
@MartinCupela MartinCupela force-pushed the feat/enhanced-mentions branch from b154ab1 to 8bc5ceb Compare June 1, 2026 11:28
Comment thread src/components/TextareaComposer/SuggestionList/BroadcastMentionItem.tsx Outdated
Comment thread src/components/ListItemLayout/ListItemLayout.tsx Outdated
Comment thread src/components/TextareaComposer/SuggestionList/RoleItem.tsx Outdated
@MartinCupela MartinCupela force-pushed the feat/enhanced-mentions branch from f59965d to 70241a5 Compare June 1, 2026 15:41
@MartinCupela MartinCupela requested a review from oliverlaz June 1, 2026 15:43
# Conflicts:
#	src/components/Message/__tests__/__snapshots__/MessageText.test.tsx.snap
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a reusable ListItemLayout component for polymorphic list rendering, expands the mention system to support channels, roles, here notifications, and user groups alongside users, and refactors suggestion list mention rendering with dedicated components for each mention type. Message rendering now passes enriched mention metadata to support more expressive mention display and matching.

Changes

ListItemLayout Component and Icon Infrastructure

Layer / File(s) Summary
Icon Exports
src/components/Icons/icons.tsx
Three new icons added: IconMegaphone, IconShield, IconUsers via createIcon with SVG paths.
ListItemLayout Component
src/components/ListItemLayout/ListItemLayout.tsx, src/components/ListItemLayout/__tests__/ListItemLayout.test.tsx
Polymorphic ListItemLayout component renders configurable root elements (div, button, etc.) with optional leading/trailing icons or slots, selected/destructive state modifiers, and nested ListItemLayoutContent for title/subtitle/description fields. Tests verify default rendering, button type handling, icon/slot counts, and ContentSlot customization.
ListItemLayout Styling
src/components/ListItemLayout/styling/ListItemLayout.scss, src/components/ListItemLayout/styling/index.scss
Complete SCSS styling for str-chat__list-item-layout covering flex layout, state selectors (selected, destructive, disabled, button), grid-based content arrangement, icon sizing, and typography via mixins.
Avatar FallbackIcon
src/components/Avatar/Avatar.tsx, src/components/Avatar/__tests__/Avatar.test.tsx
Avatar component now accepts optional FallbackIcon prop (React component type) to customize icon when no image/initials, defaulting to IconUser.
Button Theme-Inverse
src/components/Button/styling/Button.scss
New .str-chat__theme-inverse modifier overrides button text and border CSS variables using *-on-dark variants with fallback to base variables.
ListItemLayout Exports
src/components/ListItemLayout/index.ts, src/components/index.ts, src/styling/index.scss
Barrel exports forward ListItemLayout public API; global component export and Sass module import added.

Mention System Refactor and Message Integration

Layer / File(s) Summary
Mention Entity Types
src/components/Message/renderText/rehypePlugins/mentionsMarkdownPlugin.ts
New RenderTextMentionEntity and RenderTextMentionMetadata types support users, channels, here, roles, user groups. Helpers getMentionDisplayTexts() and getRenderTextMentionEntities() compute display variations and build mention lists from message metadata.
Mentions Markdown Plugin Refactor
src/components/Message/renderText/rehypePlugins/mentionsMarkdownPlugin.ts
Plugin refactored from users-only regex-based matching to lookup-driven system supporting all entity types. Precomputes @displayText map, sorts by length for greedy matching, and generalizes email-like split-node handling. API now overloads to accept UserResponse[] or RenderTextMentionEntity[].
Mention Component Update
src/components/Message/renderText/componentRenderers/Mention.tsx
Mention renders from mentionedEntity instead of mentionedUser. Sets data-mention-id/data-mention-type from mentionedEntity; data-user-id conditionally set for user mentions. UserMentionNode/NonUserMentionNode types derived via Extract/Exclude.
RenderText Options and Function
src/components/Message/renderText/renderText.tsx
RenderTextOptions extended with messageMentionEntities field. New RenderTextFunction type exported. renderText converted from arrow to function export, computing renderTextMentionEntities from messageMentionEntities or mentionedUsers fallback.
Message Text Integration
src/components/Message/MessageText.tsx, src/components/Message/__tests__/MessageText.test.tsx
MessageText computes messageMentionEntities from message.mentioned_* fields and passes to renderText. New test verifies @channel, @here, role, and user-group mention rendering with correct data-mention-type and accessibility.
Quoted Message Integration
src/components/MessageComposer/QuotedMessagePreview.tsx, src/components/Message/__tests__/QuotedMessage.test.tsx
QuotedMessagePreview computes quotedMessageMentionEntities and passes to renderText. New test validates mention rendering in quoted context.
Message Context and Props Types
src/components/Message/types.ts, src/context/MessageContext.tsx
MessageProps and MessageContextValue renderText types updated to use shared RenderTextFunction instead of inline signatures.
RenderText Tests
src/components/Message/renderText/__tests__/renderText.test.tsx
Comprehensive tests covering role/user-group mention parsing, email-pattern matching, multi-word handling, backward compatibility with UserResponse[], and data-mention-id/data-mention-type attribute validation.

Suggestion List Component Refactoring

Layer / File(s) Summary
Mention Item Base Types
src/components/TextareaComposer/SuggestionList/MentionItem/types.ts
MentionItemComponentProps generic type combining entity data, focused flag, and button component props.
TokenizedSuggestionParts
src/components/TextareaComposer/SuggestionList/TokenizedSuggestionParts.tsx
Presentational component rendering tokenizedDisplayName.parts with CSS classes for matched/non-matched tokens; replaces edge whitespace with non-breaking spaces.
MentionSuggestionTitle
src/components/TextareaComposer/SuggestionList/MentionItem/MentionSuggestionTitle.tsx
Simple component rendering children prefixed with @.
User/Broadcast/Role/UserGroup/Special Item Components
src/components/TextareaComposer/SuggestionList/MentionItem/{UserItem,BroadcastMentionItem,RoleItem,UserGroupItem,SpecialMentionItem}.tsx
Five mention item components, each rendering a specific mention type via ListItemLayout button with appropriate icon (Avatar for user, Megaphone for broadcast, Shield for role, Users for user-group) and localized metadata.
MentionItem Dispatcher
src/components/TextareaComposer/SuggestionList/MentionItem/MentionItem.tsx, src/components/TextareaComposer/SuggestionList/MentionItem/index.ts
MentionItem component dispatches to sub-components based on entity.mentionType with support for overriding any via props; barrel export of all MentionItem modules.
SuggestionList Integration
src/components/TextareaComposer/SuggestionList/SuggestionList.tsx, src/components/TextareaComposer/SuggestionList/SuggestionListItem.tsx, src/components/TextareaComposer/SuggestionList/index.ts
SuggestionList renders MentionItem instead of UserItem for @ trigger; aria-label logic updated for mentions; DefaultSuggestionListItemEntity type updated; barrel exports include CommandItem, EmoticonItem, MentionItem, TokenizedSuggestionParts, exclude UserItem.
SuggestionList Styling
src/components/TextareaComposer/styling/SuggestionList.scss
Expanded SCSS for mention layout, icon presentation, content flex layout, typography via font mixins, and text overflow handling.
TextareaComposer Keyboard Fixes
src/components/TextareaComposer/TextareaComposer.tsx
Enter key checks for non-null item before selection; ArrowDown wraps based on loadedItems.length; focus index clamped to last available item.
Suggestion Tests
src/components/MessageComposer/__tests__/MessageInput.test.tsx, src/components/TextareaComposer/__tests__/MentionItem.test.tsx
Extended MessageInput tests for mixed mention types, aria-labels, keyboard selection; comprehensive MentionItem suite verifying channel/here/role/user-group rendering, fallback icons, accessibility, and component overrides.

Internationalization Updates

Layer / File(s) Summary
i18n Mention Keys
src/i18n/{de,en,es,fr,hi,it,ja,ko,nl,pt,ru,tr}.json
All 12 locale files updated with aria/Mention Suggestions, mention/Channel/Description, mention/Here/Description, Notify all {{ role }} members keys; aria/User Suggestions changed to literal key string across all locales.

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • arnautov-anton

Poem

🐰 A mention system springs to life,
With channels, roles, and groups in flight,
New layouts bloom in ListItemLayout,
Each mention type now has its route!
From icons bright to i18n's call,
This PR brings richer mentions for all!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add enhanced mentions' directly describes the main change: adding enhanced mentions support to stream-chat-react for both composer UI and message rendering.
Description check ✅ Passed The PR description follows the template with all three required sections (🎯 Goal, 🛠 Implementation details, 🎨 UI Changes) and provides comprehensive details about the enhanced mentions feature implementation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/enhanced-mentions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/Message/MessageText.tsx (1)

81-83: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Gate mention keyboard interaction on all rendered mention entities, not just users.

renderTextMentionEntities now includes channel/here/role/user-group mentions, but isMentionsInteractionEnabled still keys off message.mentioned_users only. A message that contains only @channel, @here, a role, or a user group will render mention spans, yet the inner wrapper stays unfocusable and Enter/Space never reaches onMentionsClickMessage.

Suggested change
-  const hasMentionedUsers = Boolean(message.mentioned_users?.length);
+  const hasMentions = renderTextMentionEntities.length > 0;
   const isMentionsInteractionEnabled =
-    hasMentionedUsers && typeof onMentionsClickMessage === 'function';
+    hasMentions && typeof onMentionsClickMessage === 'function';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Message/MessageText.tsx` around lines 81 - 83, The
keyboard-interaction gating currently uses hasMentionedUsers and thus misses
non-user mentions; replace that check with a broader detection (e.g.,
hasMentionEntities) that returns true when any mention entity arrays exist or
when renderTextMentionEntities would produce mention spans — check fields like
message.mentioned_users, message.mentioned_roles, message.mentioned_groups,
message.mentioned_channels, and any "everyone"/"here"/"channel" indicator (or
fallback to examining the rendered entities output) and use that in
isMentionsInteractionEnabled alongside typeof onMentionsClickMessage to ensure
Enter/Space are focusable and routed to onMentionsClickMessage for all mention
types referenced by renderTextMentionEntities.
🧹 Nitpick comments (5)
src/components/TextareaComposer/SuggestionList/MentionItem/UserGroupItem.tsx (1)

17-17: ⚡ Quick win

Remove unnecessary void statement.

The void focused; statement appears to be dead code since focused is actually used on line 34 (selected={focused}). This statement serves no purpose and should be removed for clarity.

♻️ Proposed fix
   ...buttonProps
 }: UserGroupItemProps) => {
-  void focused;
-
   return (
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/TextareaComposer/SuggestionList/MentionItem/UserGroupItem.tsx`
at line 17, Remove the stray "void focused;" dead statement in
UserGroupItem.tsx; the variable focused is actually used later (e.g., passed to
selected={focused}) so simply delete that line to avoid the no-op and keep the
code clear while leaving the focused variable usage intact.
src/components/TextareaComposer/SuggestionList/TokenizedSuggestionParts.tsx (1)

13-31: ⚡ Quick win

Consider memoizing this component for better autocomplete performance.

TokenizedSuggestionParts will re-render whenever its parent suggestion item re-renders during autocomplete typing. Since this is in the hot path of the suggestion dropdown, wrapping it with React.memo would prevent unnecessary re-renders when tokenizedDisplayName hasn't changed.

♻️ Suggested memoization
-export const TokenizedSuggestionParts = ({
+export const TokenizedSuggestionParts = React.memo(({
   tokenizedDisplayName,
-}: TokenizedSuggestionPartsProps) =>
+}: TokenizedSuggestionPartsProps) => {
+  return (
+    <>
+      {tokenizedDisplayName.parts.map((part, i) => {
-  tokenizedDisplayName.parts.map((part, i) => {
     const matches = part.toLowerCase() === tokenizedDisplayName.token;
     const partWithHTMLSpacesAround = part.replace(/^\s+|\s+$/g, '\u00A0');

     return (
       <span
         className={clsx({
           'str-chat__emoji-item-part': !matches,
           'str-chat__suggestion-item-part--match': matches,
         })}
         key={`part-${i}`}
       >
         {partWithHTMLSpacesAround}
       </span>
     );
-  });
+      })}
+    </>
+  );
+});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/TextareaComposer/SuggestionList/TokenizedSuggestionParts.tsx`
around lines 13 - 31, Wrap the TokenizedSuggestionParts functional component
with React.memo so it only re-renders when its props change; specifically
memoize the exported TokenizedSuggestionParts (which takes tokenizedDisplayName:
TokenizedSuggestionPartsProps) to avoid re-rendering on parent updates during
autocomplete and ensure the memo key uses the default shallow prop comparison
(or provide a custom comparison that deeply compares tokenizedDisplayName if
necessary).
src/components/MessageComposer/__tests__/MessageInput.test.tsx (1)

1311-1379: ⚡ Quick win

Cover the actual wraparound branch.

This test sets hasNext: true, but it never moves past the last loaded suggestion, so it does not exercise the new nextIndex >= loadedItems.length path in src/components/TextareaComposer/TextareaComposer.tsx Line 209. Add one more ArrowDown from @here and assert that selection wraps back to @channel; otherwise the changed boundary behavior can regress unnoticed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/MessageComposer/__tests__/MessageInput.test.tsx` around lines
1311 - 1379, Test does not exercise the wraparound branch (nextIndex >=
loadedItems.length) in TextareaComposer.tsx; update the MessageInput.test.tsx
test so after selecting '`@here`' you fire one more ArrowDown key event to move
past the last loaded suggestion, then assert the selection wraps to '`@channel`'
(e.g., fire another fireEvent.keyDown(formElement, { key: 'ArrowDown' }) before
confirming with Enter and expect formElement toHaveValue('`@channel` ')).
Reference the suggestions/searchSource usage in this test and the nextIndex >=
loadedItems.length behavior in TextareaComposer.tsx when adding the extra
ArrowDown + assertion.
src/components/MessageComposer/QuotedMessagePreview.tsx (1)

409-411: 💤 Low value

Consider removing redundant mentioned_users parameter.

The renderText call passes both quotedMessage?.mentioned_users (deprecated parameter) and messageMentionEntities: quotedMessageMentionEntities (new option), where quotedMessageMentionEntities already includes the mentioned users. Since renderText derives entities from messageMentionEntities when present (line 149-151 in renderText.tsx), the deprecated parameter is unused here.

♻️ Simplify by removing redundant parameter
-      renderedText = renderText(quotedMessageText, quotedMessage?.mentioned_users, {
+      renderedText = renderText(quotedMessageText, undefined, {
         messageMentionEntities: quotedMessageMentionEntities,
       });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/MessageComposer/QuotedMessagePreview.tsx` around lines 409 -
411, The renderText call is passing a deprecated second argument
quotedMessage?.mentioned_users while also supplying messageMentionEntities:
quotedMessageMentionEntities in the options; because renderText prefers
messageMentionEntities (see renderText), remove the redundant
quotedMessage?.mentioned_users argument from the renderedText invocation and
rely solely on the options object (messageMentionEntities:
quotedMessageMentionEntities) so entities are derived from
quotedMessageMentionEntities; update the call site in QuotedMessagePreview.tsx
where renderedText = renderText(quotedMessageText,
quotedMessage?.mentioned_users, { messageMentionEntities:
quotedMessageMentionEntities }) to the single-argument form using the options
object.
src/components/Message/types.ts (1)

73-74: ⚡ Quick win

Update the renderText prop docs to match the new contract.

This prop now exposes RenderTextFunction, but the JSDoc still points to the old utils location and doesn't mention the new options.messageMentionEntities path or the deprecated mentionedUsers argument. Please refresh the inline docs here, and any matching guide page if this prop is documented externally. As per coding guidelines, src/**/*.{ts,tsx}: Ensure public API changes include documentation updates.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Message/types.ts` around lines 73 - 74, Update the JSDoc for
the renderText?: RenderTextFunction prop to reflect the new contract: remove the
old utils link, describe that the function receives (text, options) where
mention data is now available at options.messageMentionEntities (and note the
mentionedUsers argument is deprecated), and briefly document expected return
values/behavior; update any matching external docs or guide pages that reference
the old signature to use RenderTextFunction and the new
options.messageMentionEntities path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/Avatar/__tests__/Avatar.test.tsx`:
- Around line 69-74: The test in Avatar.test.tsx expects the wrong CSS class for
custom fallback icons; update the assertion in the 'should render a custom
fallback icon when provided and no initials are available' case to look for the
class produced by createIcon (use 'str-chaticon--megaphone' for IconMegaphone)
instead of '.str-chat__icon--megaphone' so the check on the rendered Avatar (use
AVATAR_ROOT_TEST_ID and the FallbackIcon=IconMegaphone usage) matches the
createIcon naming convention.

In `@src/components/ListItemLayout/styling/ListItemLayout.scss`:
- Around line 3-10: The stylesheet is failing stylelint's
declaration-empty-line-before rule for the custom property and the later
declarations; add a blank line immediately before the flagged declarations to
satisfy the rule. Specifically, insert an empty line before the
--list-item-padding declaration in the .str-chat__list-item-layout selector and
likewise add an empty line before the other flagged declaration(s) (e.g., the
padding declaration around the same selector or at the later block near lines
38–40) so the rule no longer reports errors.

In `@src/components/Message/__tests__/MessageText.test.tsx`:
- Around line 377-405: Add assertions to the existing test ("renders built-in,
role, and user-group mentions with mention styling") to verify keyboard
accessibility: for each mention found via getByText('`@channel`'),
getByText('`@here`'), getByText('`@admin`'), and getByText('`@Backend` Team') locate
the surrounding mention wrapper (e.g.,
element.closest('.str-chat__message-mention') or the element returned by
renderMessageText) and assert it is focusable by checking it has tabindex="0"
(or element.tabIndex === 0); ensure these extra expect checks are added after
the current attribute assertions and before the axe accessibility check so the
regression for focus/Enter on non-user mentions is covered.

In `@src/components/Message/MessageText.tsx`:
- Around line 55-57: In MessageText.tsx, replace the incorrect use of
message.mentioned_groups with message.mentioned_group_ids when calling
getRenderTextMentionEntities and update the helper/types used by
getRenderTextMentionEntities to accept mentioned_group_ids (or map
mentioned_group_ids -> expected shape) so TypeScript no longer reports TS2551;
also ensure isMentionsInteractionEnabled’s gating logic is updated so mention
interaction is enabled for group mentions (not just mentioned_users) when those
entities are rendered.

In `@src/components/TextareaComposer/styling/SuggestionList.scss`:
- Around line 42-60: The SCSS violates stylelint's declaration-empty-line-before
rule: in .str-chat__suggestion-list__item-title and
.str-chat__suggestion-list__item-details, add a blank line before any property
declaration that immediately follows an `@include` (i.e., ensure there is an empty
line between the `@include` utils.ellipsis-text; and the next declaration such as
text-align: start; or color: ...), so update those selectors (and similarly
.str-chat__list-item-layout__title.str-chat__suggestion-list__mention-item-title
if needed) to insert the required empty lines after mixins to satisfy linting.

In `@src/components/TextareaComposer/SuggestionList/SuggestionList.tsx`:
- Around line 223-235: The current compatibility check uses the translated
string value via legacyUserSuggestionsLabel which relies on locale bundles;
instead update the mentions branch in the suggestionMenuLabel computation to
resolve the new key with the old key as a fallback by calling t('aria/Mention
Suggestions', { defaultValue: t('aria/User Suggestions') }), remove the runtime
comparison to legacyUserSuggestionsLabel, and keep the other branches that use
t('aria/Command Suggestions') and t('aria/Emoji Suggestions') unchanged so
suggestions.searchSource.type still drives selection.

In `@src/i18n/ja.json`:
- Line 144: Replace the English value for the JSON key "aria/User Suggestions"
with the correct Japanese translation (e.g., "ユーザー候補") so the value is in
Japanese (not "aria/User Suggestions"); update the entry for "aria/User
Suggestions" in the ja.json translations and then run yarn validate-translations
to ensure the file passes validation.

In `@src/i18n/ko.json`:
- Line 144: The translation for the JSON key "aria/User Suggestions" currently
uses the English key as its value; update the value to the correct Korean
translation (e.g., "사용자 제안") for the key "aria/User Suggestions" in
src/i18n/ko.json, ensure the value is a non-empty Korean string consistent with
other aria entries (see "aria/Mention Suggestions"), and run yarn
validate-translations after the change.

In `@src/i18n/nl.json`:
- Line 145: The JSON entry for the translation key "aria/User Suggestions"
currently uses the English key as its value; replace that value with the correct
Dutch translation (e.g., "Gebruikerssuggesties") for the "aria/User Suggestions"
key in the nl.json translations so Dutch users see localized text, then run yarn
validate-translations to ensure all translations are valid.

In `@src/i18n/pt.json`:
- Line 153: Update the translation value for the JSON key "aria/User
Suggestions" so it is a Portuguese string (e.g., "Sugestões de usuários")
instead of the English key; locate the "aria/User Suggestions" entry in the
pt.json translations and replace the value with the correct Portuguese
translation, ensure the string is non-empty and matches style of other entries
like "aria/Mention Suggestions", then run `yarn validate-translations` to
confirm no validation errors.

In `@src/i18n/ru.json`:
- Line 162: The JSON key "aria/User Suggestions" has an untranslated value;
update its value to the correct Russian string (e.g., the localized aria label
for "User Suggestions") in the ru.json entry for "aria/User Suggestions", then
search other src/i18n/*.json files for any identical untranslated key/value
pairs and correct them as needed; finally run yarn validate-translations to
ensure all locale files pass validation.

---

Outside diff comments:
In `@src/components/Message/MessageText.tsx`:
- Around line 81-83: The keyboard-interaction gating currently uses
hasMentionedUsers and thus misses non-user mentions; replace that check with a
broader detection (e.g., hasMentionEntities) that returns true when any mention
entity arrays exist or when renderTextMentionEntities would produce mention
spans — check fields like message.mentioned_users, message.mentioned_roles,
message.mentioned_groups, message.mentioned_channels, and any
"everyone"/"here"/"channel" indicator (or fallback to examining the rendered
entities output) and use that in isMentionsInteractionEnabled alongside typeof
onMentionsClickMessage to ensure Enter/Space are focusable and routed to
onMentionsClickMessage for all mention types referenced by
renderTextMentionEntities.

---

Nitpick comments:
In `@src/components/Message/types.ts`:
- Around line 73-74: Update the JSDoc for the renderText?: RenderTextFunction
prop to reflect the new contract: remove the old utils link, describe that the
function receives (text, options) where mention data is now available at
options.messageMentionEntities (and note the mentionedUsers argument is
deprecated), and briefly document expected return values/behavior; update any
matching external docs or guide pages that reference the old signature to use
RenderTextFunction and the new options.messageMentionEntities path.

In `@src/components/MessageComposer/__tests__/MessageInput.test.tsx`:
- Around line 1311-1379: Test does not exercise the wraparound branch (nextIndex
>= loadedItems.length) in TextareaComposer.tsx; update the MessageInput.test.tsx
test so after selecting '`@here`' you fire one more ArrowDown key event to move
past the last loaded suggestion, then assert the selection wraps to '`@channel`'
(e.g., fire another fireEvent.keyDown(formElement, { key: 'ArrowDown' }) before
confirming with Enter and expect formElement toHaveValue('`@channel` ')).
Reference the suggestions/searchSource usage in this test and the nextIndex >=
loadedItems.length behavior in TextareaComposer.tsx when adding the extra
ArrowDown + assertion.

In `@src/components/MessageComposer/QuotedMessagePreview.tsx`:
- Around line 409-411: The renderText call is passing a deprecated second
argument quotedMessage?.mentioned_users while also supplying
messageMentionEntities: quotedMessageMentionEntities in the options; because
renderText prefers messageMentionEntities (see renderText), remove the redundant
quotedMessage?.mentioned_users argument from the renderedText invocation and
rely solely on the options object (messageMentionEntities:
quotedMessageMentionEntities) so entities are derived from
quotedMessageMentionEntities; update the call site in QuotedMessagePreview.tsx
where renderedText = renderText(quotedMessageText,
quotedMessage?.mentioned_users, { messageMentionEntities:
quotedMessageMentionEntities }) to the single-argument form using the options
object.

In
`@src/components/TextareaComposer/SuggestionList/MentionItem/UserGroupItem.tsx`:
- Line 17: Remove the stray "void focused;" dead statement in UserGroupItem.tsx;
the variable focused is actually used later (e.g., passed to selected={focused})
so simply delete that line to avoid the no-op and keep the code clear while
leaving the focused variable usage intact.

In `@src/components/TextareaComposer/SuggestionList/TokenizedSuggestionParts.tsx`:
- Around line 13-31: Wrap the TokenizedSuggestionParts functional component with
React.memo so it only re-renders when its props change; specifically memoize the
exported TokenizedSuggestionParts (which takes tokenizedDisplayName:
TokenizedSuggestionPartsProps) to avoid re-rendering on parent updates during
autocomplete and ensure the memo key uses the default shallow prop comparison
(or provide a custom comparison that deeply compares tokenizedDisplayName if
necessary).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aea911be-dcf9-4f80-a8da-7398c0d0a4b0

📥 Commits

Reviewing files that changed from the base of the PR and between 4c934ae and 6b507ce.

⛔ Files ignored due to path filters (1)
  • src/components/Message/renderText/__tests__/__snapshots__/renderText.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (51)
  • src/components/Avatar/Avatar.tsx
  • src/components/Avatar/__tests__/Avatar.test.tsx
  • src/components/Button/styling/Button.scss
  • src/components/Icons/icons.tsx
  • src/components/ListItemLayout/ListItemLayout.tsx
  • src/components/ListItemLayout/__tests__/ListItemLayout.test.tsx
  • src/components/ListItemLayout/index.ts
  • src/components/ListItemLayout/styling/ListItemLayout.scss
  • src/components/ListItemLayout/styling/index.scss
  • src/components/Message/MessageText.tsx
  • src/components/Message/__tests__/MessageText.test.tsx
  • src/components/Message/__tests__/QuotedMessage.test.tsx
  • src/components/Message/renderText/__tests__/renderText.test.tsx
  • src/components/Message/renderText/componentRenderers/Mention.tsx
  • src/components/Message/renderText/rehypePlugins/mentionsMarkdownPlugin.ts
  • src/components/Message/renderText/renderText.tsx
  • src/components/Message/types.ts
  • src/components/MessageComposer/QuotedMessagePreview.tsx
  • src/components/MessageComposer/__tests__/MessageInput.test.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/BroadcastMentionItem.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/MentionItem.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/MentionSuggestionTitle.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/RoleItem.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/SpecialMentionItem.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/UserGroupItem.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/UserItem.tsx
  • src/components/TextareaComposer/SuggestionList/MentionItem/index.ts
  • src/components/TextareaComposer/SuggestionList/MentionItem/types.ts
  • src/components/TextareaComposer/SuggestionList/SuggestionList.tsx
  • src/components/TextareaComposer/SuggestionList/SuggestionListItem.tsx
  • src/components/TextareaComposer/SuggestionList/TokenizedSuggestionParts.tsx
  • src/components/TextareaComposer/SuggestionList/UserItem.tsx
  • src/components/TextareaComposer/SuggestionList/index.ts
  • src/components/TextareaComposer/TextareaComposer.tsx
  • src/components/TextareaComposer/__tests__/MentionItem.test.tsx
  • src/components/TextareaComposer/styling/SuggestionList.scss
  • src/components/index.ts
  • src/context/MessageContext.tsx
  • src/i18n/de.json
  • src/i18n/en.json
  • src/i18n/es.json
  • src/i18n/fr.json
  • src/i18n/hi.json
  • src/i18n/it.json
  • src/i18n/ja.json
  • src/i18n/ko.json
  • src/i18n/nl.json
  • src/i18n/pt.json
  • src/i18n/ru.json
  • src/i18n/tr.json
  • src/styling/index.scss
💤 Files with no reviewable changes (1)
  • src/components/TextareaComposer/SuggestionList/UserItem.tsx

Comment on lines +69 to +74
it('should render a custom fallback icon when provided and no initials are available', () => {
const { getByTestId } = render(<Avatar FallbackIcon={IconMegaphone} size='md' />);
const root = getByTestId(AVATAR_ROOT_TEST_ID);

expect(root.querySelector('.str-chat__icon--megaphone')).toBeInTheDocument();
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the createIcon implementation to confirm class name generation
cat src/components/Icons/createIcon.tsx

Repository: GetStream/stream-chat-react

Length of output: 1923


🌐 Web query:

GetStream stream-chat-react createIcon.tsx str-chat__icon-- class name generation

💡 Result:

In the stream-chat-react library, the str-chaticon-- class name prefix is generated dynamically based on the icon name provided to the createIcon utility function [1][2]. The createIcon function utilizes a helper function named toIconClass(name: string) to transform the icon name into the appropriate CSS class [1]. For instance, an icon named IconArrowLeft will be processed to generate a class similar to str-chaticon--arrow-left [1][2]. Key points regarding this generation process: 1. Dynamic Generation: The toIconClass function performs string manipulation on the icon's identifier (often removing the "Icon" prefix and converting camelCase to kebab-case) to ensure the resulting CSS class adheres to the project's BEM-like naming convention [1][2]. 2. CSS Mapping: These auto-derived class names correspond to selectors defined in the project's SCSS files (e.g., Icons.scss), which handle styling such as sizing, coloring, and RTL (right-to-left) transformations [1][3]. 3. History: Recent updates to the library (such as the migration to the Phosphor icon set) involved updating these constants, which in turn updated the auto-derived CSS class names across the application [2]. Developers customizing these icons must ensure their CSS selectors match these generated class names [4]. While stream-chat-css historically relied on Fontello to generate icon fonts with this specific prefix [5][6], the modern stream-chat-react implementation uses the createIcon utility to manage icon components and their associated classes directly within the React package [1][2].

Citations:


Update Avatar fallback icon test to match createIcon CSS class naming
createIcon derives icon classes using str-chaticon--<kebab-cased-icon-name> (e.g., IconArrowLeftstr-chaticon--arrow-left), so the expectation should not use .str-chat__icon--megaphone; update the test to the str-chaticon--megaphone (or whatever the generated prefix is) class.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Avatar/__tests__/Avatar.test.tsx` around lines 69 - 74, The
test in Avatar.test.tsx expects the wrong CSS class for custom fallback icons;
update the assertion in the 'should render a custom fallback icon when provided
and no initials are available' case to look for the class produced by createIcon
(use 'str-chaticon--megaphone' for IconMegaphone) instead of
'.str-chat__icon--megaphone' so the check on the rendered Avatar (use
AVATAR_ROOT_TEST_ID and the FallbackIcon=IconMegaphone usage) matches the
createIcon naming convention.

Comment on lines +3 to +10
.str-chat__list-item-layout {
--list-item-padding: var(--str-chat__spacing-xs) var(--str-chat__spacing-sm);
display: flex;
align-items: center;
gap: var(--str-chat__spacing-sm);
text-align: start;
padding: var(--list-item-padding);
width: 100%;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the current Stylelint failures in this file.

Lines 5 and 40 are already flagged by declaration-empty-line-before, so this stylesheet will not pass lint as written.

Suggested change
 .str-chat__list-item-layout {
   --list-item-padding: var(--str-chat__spacing-xs) var(--str-chat__spacing-sm);
+
   display: flex;
   align-items: center;
   gap: var(--str-chat__spacing-sm);
@@
   &:is(button) {
     `@include` utils.button-reset;
+
     padding: var(--list-item-padding);
     cursor: pointer;

Also applies to: 38-40

🧰 Tools
🪛 Stylelint (17.12.0)

[error] 5-5: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ListItemLayout/styling/ListItemLayout.scss` around lines 3 -
10, The stylesheet is failing stylelint's declaration-empty-line-before rule for
the custom property and the later declarations; add a blank line immediately
before the flagged declarations to satisfy the rule. Specifically, insert an
empty line before the --list-item-padding declaration in the
.str-chat__list-item-layout selector and likewise add an empty line before the
other flagged declaration(s) (e.g., the padding declaration around the same
selector or at the later block near lines 38–40) so the rule no longer reports
errors.

Comment on lines +377 to +405
it('renders built-in, role, and user-group mentions with mention styling', async () => {
const text = 'Hello @channel @here @admin @Backend Team';
const message = generateAliceMessage({
mentioned_channel: true,
mentioned_groups: [
fromPartial({
created_at: '2026-05-28T00:00:00.000Z',
id: 'backend-team',
name: 'Backend Team',
updated_at: '2026-05-28T00:00:00.000Z',
}),
],
mentioned_here: true,
mentioned_roles: ['admin'],
text,
});
const { container, getByText } = await renderMessageText({
customProps: { message },
});

expect(getByText('@channel')).toHaveAttribute('data-mention-type', 'channel');
expect(getByText('@here')).toHaveAttribute('data-mention-type', 'here');
expect(getByText('@admin')).toHaveAttribute('data-mention-type', 'role');
expect(getByText('@Backend Team')).toHaveAttribute('data-mention-type', 'user_group');
expect(container.querySelectorAll('.str-chat__message-mention')).toHaveLength(4);

const results = await axe(container);
expect(results).toHaveNoViolations();
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Extend this regression to cover keyboard accessibility for non-user mentions.

This test proves the spans render, but it won't catch the current focus/Enter regression for messages that only contain @channel/role/group mentions. Please assert the inner wrapper becomes focusable for this payload so the accessibility path stays covered.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Message/__tests__/MessageText.test.tsx` around lines 377 -
405, Add assertions to the existing test ("renders built-in, role, and
user-group mentions with mention styling") to verify keyboard accessibility: for
each mention found via getByText('`@channel`'), getByText('`@here`'),
getByText('`@admin`'), and getByText('`@Backend` Team') locate the surrounding
mention wrapper (e.g., element.closest('.str-chat__message-mention') or the
element returned by renderMessageText) and assert it is focusable by checking it
has tabindex="0" (or element.tabIndex === 0); ensure these extra expect checks
are added after the current attribute assertions and before the axe
accessibility check so the regression for focus/Enter on non-user mentions is
covered.

Comment on lines +55 to +57
getRenderTextMentionEntities({
mentioned_channel: message.mentioned_channel,
mentioned_groups: message.mentioned_groups,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Enhanced mention fields referenced in message surfaces:"
rg -n --type=ts --type=tsx '\bmentioned_(channel|groups|here|roles|users)\b' src/components/Message src/context

echo
echo "Current LocalMessage usages on message surfaces:"
rg -n --type=ts --type=tsx '\bLocalMessage\b' src/components/Message src/context

Repository: GetStream/stream-chat-react

Length of output: 1923


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Check for enhanced mention fields in MessageText.tsx:"
rg -n --type=ts --type=tsx '\bmentioned_(channel|groups|here|roles|users)\b' src/components/Message/MessageText.tsx || true

echo
echo "Check for LocalMessage typing in MessageText.tsx:"
rg -n --type=ts --type=tsx '\bLocalMessage\b' src/components/Message/MessageText.tsx || true

Repository: GetStream/stream-chat-react

Length of output: 1942


🌐 Web query:

stream-chat LocalMessage mentioned_groups field TypeScript

💡 Result:

In the GetStream Chat SDK for JavaScript and TypeScript, the field used to handle group mentions is named mentioned_group_ids, not mentioned_groups [1][2][3]. This field is used when sending a message to notify members of specific user groups who are also members of the channel [1][2]. It accepts an array of strings representing the unique IDs of the user groups (with a maximum of 10 groups) [1][2]. While the term mentioned_groups is commonly used in conversation to describe this feature, the technical implementation within the Message payload and the SDK's type definitions strictly uses mentioned_group_ids [1][2][3]. If you are looking at LocalMessage or other message-related types in the TypeScript SDK, you should map or reference this field as mentioned_group_ids [4][5]. Example usage: const groupMessage = await channel.sendMessage({ text: "Design team, please review!", mentioned_group_ids: ["design-team-id"], });

Citations:


Fix mention group field typing: use mentioned_group_ids instead of mentioned_groups.

  • src/components/Message/MessageText.tsx passes message.mentioned_groups into getRenderTextMentionEntities, but Stream Chat’s message/types use mentioned_group_ids for group mentions; rename/map this consistently (and align the mention-entity helper/types) to resolve the TS2551 merge blocker.
  • Re-check keyboard/focus gating (isMentionsInteractionEnabled) so interaction is enabled for mention entities beyond mentioned_users when those entities are rendered.
🧰 Tools
🪛 GitHub Actions: Size / 0_Compressed Size.txt

[error] 57-57: TypeScript (TS2551) error: Property 'mentioned_groups' does not exist on type 'LocalMessage'. Did you mean 'mentioned_roles'?

🪛 GitHub Actions: Size / Compressed Size

[error] 57-57: TypeScript (TS2551): Property 'mentioned_groups' does not exist on type 'LocalMessage'. Did you mean 'mentioned_roles'?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Message/MessageText.tsx` around lines 55 - 57, In
MessageText.tsx, replace the incorrect use of message.mentioned_groups with
message.mentioned_group_ids when calling getRenderTextMentionEntities and update
the helper/types used by getRenderTextMentionEntities to accept
mentioned_group_ids (or map mentioned_group_ids -> expected shape) so TypeScript
no longer reports TS2551; also ensure isMentionsInteractionEnabled’s gating
logic is updated so mention interaction is enabled for group mentions (not just
mentioned_users) when those entities are rendered.

Comment on lines +42 to 60
.str-chat__suggestion-list__item-title {
@include fonts.text-caption-default;
@include utils.ellipsis-text;
text-align: start;
min-width: 0;
}

.str-chat__list-item-layout__title.str-chat__suggestion-list__mention-item-title {
font: var(--str-chat__font-body-default);
}

.str-chat__suggestion-list__item-details {
@include fonts.text-metadata-default;
@include utils.ellipsis-text;
color: var(--str-chat__text-tertiary);
text-align: start;
min-width: 0;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix stylelint violations: add empty lines before declarations following mixins.

The declaration-empty-line-before rule requires an empty line before declarations that follow @include statements. Lines 45 and 56 violate this rule.

🎨 Proposed fix
   .str-chat__suggestion-list__item-title {
     `@include` fonts.text-caption-default;
     `@include` utils.ellipsis-text;
+
     text-align: start;
     min-width: 0;
   }

   .str-chat__list-item-layout__title.str-chat__suggestion-list__mention-item-title {
     font: var(--str-chat__font-body-default);
   }

   .str-chat__suggestion-list__item-details {
     `@include` fonts.text-metadata-default;
     `@include` utils.ellipsis-text;
+
     color: var(--str-chat__text-tertiary);
     text-align: start;
     min-width: 0;
   }

As per coding guidelines, the project follows a 'zero warnings' policy—fix new warnings and avoid introducing any.

🧰 Tools
🪛 Stylelint (17.12.0)

[error] 45-45: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 56-56: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/TextareaComposer/styling/SuggestionList.scss` around lines 42
- 60, The SCSS violates stylelint's declaration-empty-line-before rule: in
.str-chat__suggestion-list__item-title and
.str-chat__suggestion-list__item-details, add a blank line before any property
declaration that immediately follows an `@include` (i.e., ensure there is an empty
line between the `@include` utils.ellipsis-text; and the next declaration such as
text-align: start; or color: ...), so update those selectors (and similarly
.str-chat__list-item-layout__title.str-chat__suggestion-list__mention-item-title
if needed) to insert the required empty lines after mixins to satisfy linting.

Comment thread src/i18n/ja.json
"aria/Unmute User": "無音を解除する",
"aria/Unpin Message": "ピンを解除",
"aria/User Suggestions": "ユーザー候補",
"aria/User Suggestions": "aria/User Suggestions",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Translation value must be in Japanese, not the English key.

The value for aria/User Suggestions should be the Japanese translation (likely ユーザー候補), not the literal string aria/User Suggestions. This will cause English text to be displayed to Japanese users, breaking the i18n contract. Compare with line 97 where aria/Mention Suggestions is properly translated to メンション候補.

🌍 Proposed fix
-  "aria/User Suggestions": "aria/User Suggestions",
+  "aria/User Suggestions": "ユーザー候補",

As per coding guidelines, ensure all translation values are non-empty strings in the target language and run yarn validate-translations after fixing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"aria/User Suggestions": "aria/User Suggestions",
"aria/User Suggestions": "ユーザー候補",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/ja.json` at line 144, Replace the English value for the JSON key
"aria/User Suggestions" with the correct Japanese translation (e.g., "ユーザー候補")
so the value is in Japanese (not "aria/User Suggestions"); update the entry for
"aria/User Suggestions" in the ja.json translations and then run yarn
validate-translations to ensure the file passes validation.

Comment thread src/i18n/ko.json
"aria/Unmute User": "음소거 해제",
"aria/Unpin Message": "핀 해제",
"aria/User Suggestions": "사용자 제안",
"aria/User Suggestions": "aria/User Suggestions",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Translation value must be in Korean, not the English key.

The value for aria/User Suggestions should be the Korean translation (likely 사용자 제안), not the literal string aria/User Suggestions. This will cause English text to be displayed to Korean users. Compare with line 97 where aria/Mention Suggestions is properly translated to 멘션 제안.

🌍 Proposed fix
-  "aria/User Suggestions": "aria/User Suggestions",
+  "aria/User Suggestions": "사용자 제안",

As per coding guidelines, ensure all translation values are non-empty strings in the target language and run yarn validate-translations after fixing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"aria/User Suggestions": "aria/User Suggestions",
"aria/User Suggestions": "사용자 제안",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/ko.json` at line 144, The translation for the JSON key "aria/User
Suggestions" currently uses the English key as its value; update the value to
the correct Korean translation (e.g., "사용자 제안") for the key "aria/User
Suggestions" in src/i18n/ko.json, ensure the value is a non-empty Korean string
consistent with other aria entries (see "aria/Mention Suggestions"), and run
yarn validate-translations after the change.

Comment thread src/i18n/nl.json
"aria/Unmute User": "Dempen opheffen",
"aria/Unpin Message": "Losmaken",
"aria/User Suggestions": "Gebruikerssuggesties",
"aria/User Suggestions": "aria/User Suggestions",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Translation value must be in Dutch, not the English key.

The value for aria/User Suggestions should be the Dutch translation (likely Gebruikerssuggesties), not the literal string aria/User Suggestions. This will cause English text to be displayed to Dutch users. Compare with line 98 where aria/Mention Suggestions is properly translated to Vermeldingssuggesties.

🌍 Proposed fix
-  "aria/User Suggestions": "aria/User Suggestions",
+  "aria/User Suggestions": "Gebruikerssuggesties",

As per coding guidelines, ensure all translation values are non-empty strings in the target language and run yarn validate-translations after fixing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"aria/User Suggestions": "aria/User Suggestions",
"aria/User Suggestions": "Gebruikerssuggesties",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/nl.json` at line 145, The JSON entry for the translation key
"aria/User Suggestions" currently uses the English key as its value; replace
that value with the correct Dutch translation (e.g., "Gebruikerssuggesties") for
the "aria/User Suggestions" key in the nl.json translations so Dutch users see
localized text, then run yarn validate-translations to ensure all translations
are valid.

Comment thread src/i18n/pt.json
"aria/Unmute User": "Ativar som",
"aria/Unpin Message": "Desfixar mensagem",
"aria/User Suggestions": "Sugestões de usuários",
"aria/User Suggestions": "aria/User Suggestions",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Translation value must be in Portuguese, not the English key.

The value for aria/User Suggestions should be the Portuguese translation (likely Sugestões de usuários), not the literal string aria/User Suggestions. This will cause English text to be displayed to Portuguese users. Compare with line 106 where aria/Mention Suggestions is properly translated to Sugestões de menções.

🌍 Proposed fix
-  "aria/User Suggestions": "aria/User Suggestions",
+  "aria/User Suggestions": "Sugestões de usuários",

As per coding guidelines, ensure all translation values are non-empty strings in the target language and run yarn validate-translations after fixing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"aria/User Suggestions": "aria/User Suggestions",
"aria/User Suggestions": "Sugestões de usuários",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/pt.json` at line 153, Update the translation value for the JSON key
"aria/User Suggestions" so it is a Portuguese string (e.g., "Sugestões de
usuários") instead of the English key; locate the "aria/User Suggestions" entry
in the pt.json translations and replace the value with the correct Portuguese
translation, ensure the string is non-empty and matches style of other entries
like "aria/Mention Suggestions", then run `yarn validate-translations` to
confirm no validation errors.

Comment thread src/i18n/ru.json
"aria/Unmute User": "Включить уведомления",
"aria/Unpin Message": "Открепить сообщение",
"aria/User Suggestions": "Подсказки пользователей",
"aria/User Suggestions": "aria/User Suggestions",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check all locale files for aria/User Suggestions values

rg -n '"aria/User Suggestions":\s*"aria/User Suggestions"' 'src/i18n/*.json'

Repository: GetStream/stream-chat-react

Length of output: 1923


🏁 Script executed:

rg -n '"aria/User Suggestions":\s*"aria/User Suggestions"' src/i18n/*.json
yarn validate-translations

Repository: GetStream/stream-chat-react

Length of output: 1942


🏁 Script executed:

rg -n '"aria/User Suggestions":\s*"aria/User Suggestions"' src/i18n/*.json
yarn validate-translations

Repository: GetStream/stream-chat-react

Length of output: 1942


🏁 Script executed:

rg -n '"aria/User Suggestions":\s*"aria/User Suggestions"' src/i18n/*.json
yarn validate-translations

Repository: GetStream/stream-chat-react

Length of output: 1942


Restore proper Russian translation for "aria/User Suggestions" (src/i18n/ru.json:162)

"aria/User Suggestions" maps to the literal string "aria/User Suggestions", so Russian users will hear an untranslated aria label instead of localized text.

Replace the value with the intended Russian string, then check other src/i18n/*.json locales for the same pattern and run yarn validate-translations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/ru.json` at line 162, The JSON key "aria/User Suggestions" has an
untranslated value; update its value to the correct Russian string (e.g., the
localized aria label for "User Suggestions") in the ru.json entry for "aria/User
Suggestions", then search other src/i18n/*.json files for any identical
untranslated key/value pairs and correct them as needed; finally run yarn
validate-translations to ensure all locale files pass validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants