Skip to content

Introduce new stacked group avatars#6158

Merged
gpunto merged 9 commits intov7from
redesign/avatar-group
Feb 18, 2026
Merged

Introduce new stacked group avatars#6158
gpunto merged 9 commits intov7from
redesign/avatar-group

Conversation

@gpunto
Copy link
Contributor

@gpunto gpunto commented Feb 16, 2026

Goal

The group avatars have a new design, where we stack user avatars depending on how many there are.

Implementation

The implementation uses the channel image if there's one, otherwise it checks the number of users in the channel and switches to the appropriate layout where we display 2, 3, 4 avatars or 2 avatars + a count badge.

🎨 UI Changes

Preview

Screenshot 2026-02-16 at 16 26 17
Before After
Screenshot_20260216_162812 Screenshot_20260216_162630

Testing

Can be checked in the sample

Summary by CodeRabbit

Release Notes

  • New Features

    • Added stacked avatar support for group channels with member count overflow badges
    • Added online status indicators for avatars
    • Enhanced color theming with new avatar placeholder colors, badge variants, and selection state colors
    • Added numeric large typography style for text styling
  • Bug Fixes

    • Improved color selections for image picker selection indicators and video overlay elements
  • Refactor

    • Consolidated component logic and removed preview-only code

@gpunto gpunto added the pr:new-feature New feature label Feb 16, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.25 MB 5.66 MB 0.41 MB 🟡
stream-chat-android-ui-components 10.60 MB 10.82 MB 0.23 MB 🟢
stream-chat-android-compose 12.81 MB 11.86 MB -0.95 MB 🚀

@gpunto
Copy link
Contributor Author

gpunto commented Feb 16, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gpunto gpunto force-pushed the redesign/avatar-group branch from 2a03e87 to 7ced2e1 Compare February 16, 2026 16:16
@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

Walkthrough

This PR introduces stacked avatar rendering with overflow badges for multi-member channels, adds new color and typography theme properties, and updates UI components to use these new design tokens.

Changes

Cohort / File(s) Summary
Theme Color & Typography Updates
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamColors.kt, stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTypography.kt
Added new public color properties (avatarBgPlaceholder, avatarTextPlaceholder, badgeBgDefault, badgeTextInverse, controlRadioCheckBgSelected, controlRadioCheckIconSelected) and new numericLarge typography style. Updated default initializers with new tokens.
Avatar Components
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/Avatar.kt, stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/ChannelAvatar.kt, stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/UserAvatar.kt
Removed preview code from Avatar; refactored ChannelAvatar with stacked avatar layout support, online indicators, and overflow CountBadge for 4\+ members; made resolveIndicatorDimensions internal and added UserAvatarIconPlaceholder helper.
New Badge Component
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/common/CountBadge.kt
Added internal CountBadge composable with size presets (Large, Medium, Small) and dynamic font scaling for displaying overflow member counts.
Component Color Updates
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/attachments/images/ImagesPicker.kt
Updated selection indicator and video overlay colors to use new theme tokens: borderCoreOnAccent, controlRadioCheckBgSelected, controlRadioCheckIconSelected, badgeTextInverse.
Utilities & Resources
stream-chat-android-previewdata/src/main/kotlin/io/getstream/chat/android/previewdata/PreviewChannelData.kt, stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/extensions/Channel.kt, stream-chat-android-compose/src/main/res/values/strings.xml
Added makeChannelWithMembers utility function for testing multi-member channels; made Channel.isOneToOne public with InternalStreamChatApi annotation; added avatar overflow count string resource.
API Surface
stream-chat-android-compose/api/stream-chat-android-compose.api
Updated public API signatures for StreamColors (new component methods 113\–119, new getters, renamed copy) and StreamTypography (constructor changes, component24, new getNumericLarge getter).
Documentation
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt
Updated KDoc description for ChannelAvatar.showIndicator parameter to clarify it indicates any user online status rather than 1:1 channel user status.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • VelikovPetar

Poem

🐰 Stacked avatars hop in cheerful rows,
With overflow badges stealing the shows,
New colors dance in themes so bright,
CountBadges count members left and right! 📊
Stream Chat's compose hops faster still! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (66 files):

⚔️ stream-chat-android-compose/api/stream-chat-android-compose.api (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/previewdata/PreviewReactionOptionData.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/previewdata/PreviewUserReactionData.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/state/reactionoptions/ReactionOptionItemState.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/state/userreactions/UserReactionItemState.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/attachments/images/ImagesPicker.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/Avatar.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/ChannelAvatar.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/UserAvatar.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/reactionoptions/ExtendedReactionsOptions.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/reactionoptions/ReactionOptions.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/reactionpicker/ReactionsPicker.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/reactions/ReactionToggle.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/selectedmessage/SelectedMessageMenu.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/selectedmessage/SelectedReactionsMenu.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/userreactions/UserReactionItem.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageContainer.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatTheme.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamColors.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamDimens.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTypography.kt (content)
⚔️ stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/MessagePreviewIconFactory.kt (content)
⚔️ stream-chat-android-compose/src/main/res/values/strings.xml (content)
⚔️ stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/reactionpicker/ReactionsPickerTest.kt (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_file_attachment_preview_content.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_image_attachment_preview_content.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.attachments.content_AttachmentsContentTest_media_attachment_preview_items.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelItemTest_draft_message.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelItemTest_last_message_delivered_status.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelItemTest_last_message_pending_status.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelItemTest_last_message_seen_status.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelItemTest_last_message_sent_status.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelItemTest_muted_channel.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelItemTest_unread_messages.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelListTest_loaded_channels.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelListTest_loading_more_channels.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.channels_ChannelsTest_loaded_channels.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.attachments.images_ImagesPickerTest_add_more.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.attachments.images_ImagesPickerTest_multiple_selection.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.attachments.images_ImagesPickerTest_single_selection.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.composer_ComposerLinkPreviewTest_composer_link_preview.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.reactionpicker_ReactionsPickerTest_Default_reaction_picker.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.reactionpicker_ReactionsPickerTest_Reaction_picker_with_header.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments_AttachmentMediaPickerTest_multiple_selection.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments_AttachmentMediaPickerTest_single_selection.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageComposerInputTest_attachments.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageComposerInputTest_attachments_and_link.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageComposerInputTest_link.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageComposerInputTest_reply,_attachments,_and_link.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageComposerInputTest_reply.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListHeaderTest_connected_state.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListHeaderTest_offline_state.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListHeaderTest_thread_mode.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_scroll_to_bottom_button.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_scroll_to_bottom_button_in_dark_mode.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_my_message.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_my_message_in_dark_mode.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_their_message.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_their_message_in_dark_mode.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedReactionsMenuTest_many_reactions.png (content)
⚔️ stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedReactionsMenuTest_one_reaction.png (content)
⚔️ stream-chat-android-docs/src/main/kotlin/io/getstream/chat/docs/kotlin/compose/guides/ProvidingCustomReactions.kt (content)
⚔️ stream-chat-android-previewdata/src/main/kotlin/io/getstream/chat/android/previewdata/PreviewChannelData.kt (content)
⚔️ stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/extensions/Channel.kt (content)
⚔️ stream-chat-android-ui-guides/src/main/java/io/getstream/chat/android/guides/catalog/compose/customreactions/MessagesActivity.kt (content)

These conflicts must be resolved before merging into v7.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Introduce new stacked group avatars' accurately summarizes the main change—implementing a new stacked avatar design for groups.
Description check ✅ Passed The description covers Goal, Implementation, UI Changes with screenshots, and Testing sections, but is missing the Contributor/Reviewer Checklists and some supporting details like documentation updates.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch redesign/avatar-group
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch redesign/avatar-group
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

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

@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: 3

Caution

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

⚠️ Outside diff range comments (1)
stream-chat-android-compose/api/stream-chat-android-compose.api (1)

4078-4124: ⚠️ Potential issue | 🟡 Minor

Document the StreamTypography expansion in the changelog.

The numericLarge property and updated constructor signature expand the public API. While the factory method defaultTypography() ensures backward compatibility for typical usage, this change should be documented in CHANGELOG.md to inform downstream consumers. Consider adding an entry under the "Added" section for stream-chat-android-compose to explain the new text style property.

🤖 Fix all issues with AI agents
In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Around line 1628-1633: The API dump exposes ComposableSingletons$CountBadgeKt
(with getLambda-1$stream_chat_android_compose_release and lambda-1) as public
while CountBadge and CountBadgeSize are intended internal; either make the
CountBadge/CountBadgeSize public if that was intended or revert their visibility
to internal and regenerate the API dump so ComposableSingletons$CountBadgeKt is
not public. Locate the symbols ComposableSingletons$CountBadgeKt, CountBadge,
CountBadgeSize and the function getLambda-1$stream_chat_android_compose_release
in the codebase, adjust the Kotlin visibility modifiers to be consistent
(internal for implementation-only types or public for intended API), then re-run
the API dump generation to update the .api file so it matches the corrected
visibilities.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/ChannelAvatar.kt`:
- Around line 159-214: StackedGroupAvatar declares a showBorder parameter but
never uses or forwards it, misleading callers; either remove the parameter from
StackedGroupAvatar (and its callers such as ChannelAvatar) if stacked avatars
should not support borders, or thread showBorder into the stacked children by
adjusting how the base modifier is created—e.g., update StackedGroupAvatar to
pass showBorder into StackedGroupAvatarSpecs.baseModifier (or into UserAvatar
calls) so borders are applied consistently (refer to StackedGroupAvatar,
StackedGroupAvatarSpecs.baseModifier, and UserAvatar for where to propagate or
remove the flag).

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/common/CountBadge.kt`:
- Around line 49-67: The Text composable is incorrectly hardcoding style =
ChatTheme.typography.numericLarge instead of using the computed style from
size.textStyle(typography), causing wrong lineHeight/other text metrics for
Small badges; update the Text call to use the local style variable (style) and
keep the separately computed fontSize override (fontSize = fontSize) so metrics
come from size.textStyle(typography) while font size respects fixedFontSize
logic; refer to the computed variables style, fontSize,
size.textStyle(typography), and the Text composable to locate the change.
🧹 Nitpick comments (10)
stream-chat-android-previewdata/src/main/kotlin/io/getstream/chat/android/previewdata/PreviewChannelData.kt (1)

96-103: Add KDoc to this public function.

The existing coding guidelines require public APIs to be documented with KDoc. A brief description of the function's purpose and its parameter would suffice.

Also, consider guarding against non-positive values of howMany, or at minimum documenting the expected range, since List(-1) { ... } would throw an IllegalArgumentException at runtime.

📝 Suggested KDoc and guard
+    /**
+     * Creates a [Channel] populated with [howMany] generated [Member] entries.
+     *
+     * `@param` howMany The number of members to include. Must be positive.
+     */
     public fun makeChannelWithMembers(howMany: Int): Channel = Channel(
+        require(howMany > 0) { "howMany must be positive" }

Or, if you prefer keeping it simple for preview-only code, just the KDoc is fine.

As per coding guidelines: **/*.kt: "Document public APIs with KDoc, including thread expectations and state notes."

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTokens.kt (1)

59-59: Naming inconsistency with other lineHeight tokens.

The other line-height tokens use semantic names (lineHeightTightest, lineHeightTighter, etc.), while this one uses a raw numeric suffix. Since 12.sp sits between lineHeightTightest (10.sp) and lineHeightTighter (14.sp), consider a semantic name (e.g., lineHeightTighterSmall or similar) to stay consistent.

This is internal so the impact is limited — just a nit for consistency.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTypography.kt (1)

50-52: Missing @param KDoc for numericLarge.

The class-level KDoc documents numericMedium and numericExtraLarge but omits numericLarge. Add it for consistency. As per coding guidelines, public APIs should be documented with KDoc.

📝 Suggested addition after line 51
  * `@param` numericMedium Style for medium-sized numeric indicators, like the unread count.
+ * `@param` numericLarge Style for large-sized numeric indicators, like the avatar overflow count.
  * `@param` numericExtraLarge Style for extra-large numeric indicators.
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/UserAvatar.kt (2)

131-138: Redundant .background(background) on Icon.

The parent BoxWithConstraints at line 128 already applies .background(background). Applying it again on the Icon at line 136 is unnecessary since the Icon is centered within the parent and the parent fills its space with that background color.

♻️ Suggested fix
         Icon(
             painter = painterResource(R.drawable.stream_compose_ic_user),
             contentDescription = null,
             tint = foreground,
             modifier = Modifier
-                .background(background)
                 .size(this.maxWidth.toPlaceholderIconSize()),
         )

152-153: Consider using @StreamPreview instead of @Preview.

The coding guidelines specify that Compose previews should use @StreamPreview helpers. This preview uses the standard @Preview annotation instead.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/common/CountBadge.kt (1)

76-86: Consider using @StreamPreview instead of @Preview.

As per coding guidelines, Compose previews should use @StreamPreview helpers.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamColors.kt (2)

176-176: Missing KDoc @param entries for several new public properties.

The following new public properties are not documented in the class-level KDoc:

  • avatarBgPlaceholder
  • avatarTextPlaceholder
  • textOnDark
  • badgeBgDefault
  • badgeTextInverse
  • controlRadioCheckBgSelected
  • controlRadioCheckIconSelected

The existing KDoc documents most other properties; these should be added for consistency. As per coding guidelines, public APIs should be documented with KDoc.

Also applies to: 187-187, 213-213, 223-228, 258-259


494-495: neutral900 is declared before neutral800, breaking the numerical ordering.

All other primitive colors follow ascending numerical order. Swap these two lines for consistency.

♻️ Suggested fix
-    val neutral900 = Color(0xFF1C1C1C)
     val neutral800 = Color(0xFF323232)
+    val neutral900 = Color(0xFF1C1C1C)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/ChannelAvatar.kt (2)

137-157: alignmentsByIndex list-index mapping is subtle — consider a clarifying comment.

The list uses positional indexing to map membersCount → alignments, with index 0 holding an emptyList() and indices 1–2 both mapping to alignments2. This works, but the implicit coupling between the list index and the when branches in StackedGroupAvatar (e.g., membersCount == 1 uses alignments[0] and alignments[1] from alignments2) is easy to misread. A brief inline comment would help future readers.


194-211: showIndicator on every stacked avatar could be visually crowded at small sizes.

Each UserAvatar in the loop receives showIndicator, which means up to 4 small avatars could each render their own online indicator badge simultaneously. At AvatarSize.ExtraSmall (the Medium dimension tier), the indicators might overlap or be hard to see. If this is intentional per design, no action needed — just flagging in case it wasn't considered.

@gpunto gpunto force-pushed the redesign/avatar-group branch 2 times, most recently from 9ba648d to bef5003 Compare February 16, 2026 16:54
@gpunto
Copy link
Contributor Author

gpunto commented Feb 16, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@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: 1

🤖 Fix all issues with AI agents
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTypography.kt`:
- Around line 216-220: The numericLarge TextStyle is missing an explicit
lineHeight and should match its siblings; update the numericLarge TextStyle (in
StreamTypography) to include lineHeight = StreamTokens.lineHeightTighter so it
uses the same tighter line spacing as numericMedium and numericExtraLarge
instead of inheriting the platform default.
🧹 Nitpick comments (7)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTypography.kt (1)

78-78: Missing @param numericLarge in the class KDoc.

The KDoc block (lines 50–52) documents numericMedium and numericExtraLarge but skips the new numericLarge property. As per coding guidelines, public APIs should be documented with KDoc.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/common/CountBadge.kt (1)

76-86: Consider using @StreamPreview helper instead of raw @Preview.

As per coding guidelines, Compose previews in this module should use @StreamPreview helpers.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamColors.kt (2)

176-228: Several new public properties lack @param KDoc entries.

avatarBgPlaceholder, avatarTextPlaceholder, textOnDark, badgeBgDefault, badgeTextInverse, controlRadioCheckBgSelected, and controlRadioCheckIconSelected are all public properties without corresponding @param entries in the class-level KDoc (lines 26–141). As per coding guidelines, public APIs should be documented with KDoc.


494-495: Nit: neutral900 is declared before neutral800, breaking numeric order.

The other neutral primitives follow ascending numeric order. Consider reordering for consistency.

Suggested reorder
     val neutral700 = Color(0xFF4A4A4A)
-    val neutral900 = Color(0xFF1C1C1C)
     val neutral800 = Color(0xFF323232)
+    val neutral900 = Color(0xFF1C1C1C)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/UserAvatar.kt (2)

121-140: Redundant .background(background) on the Icon modifier.

The BoxWithConstraints on line 128 already sets .background(background). The duplicate on the Icon (line 136) is harmless but unnecessary.

Suggested cleanup
         Icon(
             painter = painterResource(R.drawable.stream_compose_ic_user),
             contentDescription = null,
             tint = foreground,
             modifier = Modifier
-                .background(background)
                 .size(this.maxWidth.toPlaceholderIconSize()),
         )

152-186: Consider using @StreamPreview helper instead of raw @Preview.

As per coding guidelines, Compose previews in this module should use @StreamPreview helpers.

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/ChannelAvatar.kt (1)

297-326: Consider using @StreamPreview helper instead of raw @Preview.

As per coding guidelines, Compose previews in this module should use @StreamPreview helpers. This applies to the other new previews in this PR as well (AvatarPreview in UserAvatar.kt, CountBadgePreview in CountBadge.kt).

@gpunto gpunto marked this pull request as ready for review February 16, 2026 17:26
@gpunto gpunto requested a review from a team as a code owner February 16, 2026 17:26
@gpunto gpunto force-pushed the redesign/avatar-group branch from bef5003 to c5dc6c4 Compare February 16, 2026 17:33
Copy link
Contributor

@andremion andremion left a comment

Choose a reason for hiding this comment

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

Good job!
Can you also check why the avatar and the channel text look inconsistent?
e.g. the avatar shows 2 members + 11, whereas the channel texts shows 2 members + 10

Image

@gpunto gpunto force-pushed the redesign/avatar-group branch from dd1b897 to a492732 Compare February 17, 2026 11:07
@gpunto
Copy link
Contributor Author

gpunto commented Feb 17, 2026

Good job! Can you also check why the avatar and the channel text look inconsistent? e.g. the avatar shows 2 members + 11, whereas the channel texts shows 2 members + 10

Good point, it's because we're excluding the current user in the channel title count. I've just asked in Figma because, as far as I understand, we're not excluding it for the avatar and we don't have examples for this case of the channel title yet.

@gpunto gpunto force-pushed the redesign/avatar-group branch from a492732 to 0fbeb6c Compare February 17, 2026 15:13
@gpunto gpunto force-pushed the redesign/avatar-group branch from 0fbeb6c to 5ea3eea Compare February 17, 2026 15:42
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
77.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@gpunto
Copy link
Contributor Author

gpunto commented Feb 18, 2026

Good job! Can you also check why the avatar and the channel text look inconsistent? e.g. the avatar shows 2 members + 11, whereas the channel texts shows 2 members + 10

Good point, it's because we're excluding the current user in the channel title count. I've just asked in Figma because, as far as I understand, we're not excluding it for the avatar and we don't have examples for this case of the channel title yet.

So, Jurgen update channel list design examples so that the title fallback logic matches the avatar logic, so we're good to go here! We'll address the inconsistency when updating the channel list design.

@gpunto gpunto merged commit d1ba3a9 into v7 Feb 18, 2026
14 of 15 checks passed
@gpunto gpunto deleted the redesign/avatar-group branch February 18, 2026 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:new-feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants