Skip to content

Conversation

@gpunto
Copy link
Contributor

@gpunto gpunto commented Jan 19, 2026

🎯 Goal

Redesigns the avatar components

🛠 Implementation details

Note: this PR only introduces the components. I'll replace the old ones in a follow up PR.

Introduce new:

  • Avatar
  • UserAvatar + placeholder
  • ChannelAvatar + placeholde
  • AvatarStack & UserAvatarStack

🎨 UI Changes

Figma

Screenshot 2026-01-19 at 14 01 30

🧪 Testing

Not visible in the sample yet, since they're not used, but you can run the compose preview.

☑️Contributor Checklist

General

  • I have signed the Stream CLA (required)
  • Assigned a person / code owner group (required)
  • Thread with the PR link started in a respective Slack channel (#android-chat-core or #android-chat-ui) (required)
  • PR is linked to the GitHub issue it resolves

Code & documentation

  • Changelog is updated with client-facing changes
  • New code is covered by unit tests
  • Comparison screenshots added for visual changes
  • Affected documentation updated (KDocs, docusaurus, tutorial)

☑️Reviewer Checklist

  • UI Components sample runs & works
  • Compose sample runs & works
  • UI Changes correct (before & after images)
  • Bugs validated (bugfixes)
  • New feature tested and works
  • Release notes and docs clearly describe changes
  • All code we touched has new or updated KDocs
  • Check the SDK Size Comparison table in the CI logs

🎉 GIF

Please provide a suitable gif that describes your work on this pull request

Summary by CodeRabbit

  • New Features

    • Added avatar UI components with online/offline status indicators, multiple sizing options, placeholder support with dynamically assigned colors based on user data, and multi-user stacking capabilities
    • Expanded application color palette with semantic colors for button styling (primary, secondary, destructive, outline, ghost), component states, presence indicators, and avatar background variations
    • Added new team and user vector icons
  • Style

    • Introduced typography emphasis variants for body, caption, and metadata text to improve visual hierarchy

✏️ Tip: You can customize this high-level summary in your review settings.

@gpunto gpunto force-pushed the redesign/avatar branch 2 times, most recently from acc1122 to bc933aa Compare January 19, 2026 13:08
</value>
</option>
</AndroidXmlCodeStyleSettings>
<JavaCodeStyleSettings>
Copy link
Contributor Author

@gpunto gpunto Jan 19, 2026

Choose a reason for hiding this comment

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

Updating this since Android Studio wants to set this style now.

I'm still not convinced we should have this file committed. I understand is to have a shared code style, but we have Spotless anyway for enforcing that.

import io.getstream.chat.android.ui.common.utils.extensions.initials

@Composable
internal fun Avatar(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

At the moment the various avatar implementations are all in this file to avoid conflicting with the existing ones. I'll move them in the follow up PR when replace old with new implementation.


import io.getstream.chat.android.core.internal.InternalStreamChatApi

internal fun String.initials(): String {
Copy link
Contributor Author

@gpunto gpunto Jan 19, 2026

Choose a reason for hiding this comment

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

Optimization to do it in O(N) time and avoid the various allocations the previous impl was doing, especially given that this is called at rendering time.

@gpunto
Copy link
Contributor Author

gpunto commented Jan 19, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 19, 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.

@coderabbitai
Copy link

coderabbitai bot commented Jan 19, 2026

Walkthrough

Introduces a new unified design token system (StreamTokens) consolidating radii and spacing, expands the theme with semantic color properties for buttons, state, presence, and avatars, adds internal avatar UI components with placeholders and online indicators, extends typography with emphasis styles, and updates utilities and resources.

Changes

Cohort / File(s) Summary
Theme Token Consolidation
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTokens.kt, StreamRadii.kt, StreamSpacings.kt
Introduced new StreamTokens object centralizing radius, spacing, and typography tokens; removed legacy StreamRadii and StreamSpacings files.
Color System Expansion
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamColors.kt
Added 40+ new semantic color properties (accent colors, avatar palette, button styles, presence indicators, state colors); expanded internal StreamPrimitiveColors with new base color constants.
Typography Updates
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTypography.kt
Added three new emphasis styles (bodyEmphasis, captionEmphasis, metadataEmphasis) initialized with StreamTokens weights and metrics.
Avatar Component Suite
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/StreamAvatar.kt, AvatarPlaceholderUtils.kt, AvatarStack.kt, OnlineIndicator.kt
Introduced internal avatar composables (Avatar, UserAvatar, ChannelAvatar) with placeholders, online indicators, stacking support, and size-aware styling.
Public API & Component Factory Updates
stream-chat-android-compose/api/stream-chat-android-compose.api, stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt
Updated API surface to reflect StreamColors/StreamTypography expansions; removed deprecated Avatar overload.
Composer & Utility Updates
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/composer/ComposerLinkPreview.kt, ui/util/ModifierUtils.kt
Updated ComposerLinkPreview to use StreamTokens; added applyIf conditional modifier extension.
Resources & Configuration
stream-chat-android-compose/src/main/res/drawable/stream_compose_ic_team.xml, stream_compose_ic_user.xml, .idea/codeStyles/Project.xml, stream-chat-android-ui-common/.../String.kt
Added new vector drawable resources (team and user icons), configured import layout rules, reimplemented String.initials() logic.

Sequence Diagram

sequenceDiagram
    participant App as App/Composable
    participant Avatar as Avatar<br/>(Composable)
    participant Theme as ChatTheme
    participant Colors as StreamColors
    participant Placeholder as AvatarPlaceholder<br/>Utility
    participant Indicator as OnlineIndicator<br/>(Composable)

    App->>Avatar: Render Avatar(user)
    Avatar->>Theme: Retrieve Colors & Typography
    Avatar->>Colors: Access colors<br/>(accentSuccess, accentNeutral)
    alt User has imageUrl
        Avatar->>Avatar: Load & display image<br/>with Crossfade
    else No image
        Avatar->>Placeholder: Generate placeholder colors<br/>& initials
        Placeholder->>Colors: Get avatarPaletteBg/Text<br/>by identifier
        Placeholder-->>Avatar: Return (bgColor, textColor)
        Avatar->>Avatar: Render initials<br/>with placeholder styling
    end
    Avatar->>Indicator: Show OnlineIndicator<br/>(if enabled)
    Indicator->>Colors: Get presenceBgOnline/Offline
    Indicator-->>Avatar: Render status badge
    Avatar-->>App: Display final Avatar UI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

compose, ui-components

Suggested reviewers

  • VelikovPetar

Poem

🐰 Hopping through tokens and colors so bright,
Avatars bloom with placeholders just right,
Online indicators twitch left and right,
Design tokens guide us through day and through night,
From StreamRadii's past to StreamTokens' light!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Introduce new Avatar designs' clearly and accurately summarizes the main change in the PR, which is the introduction of new avatar components as detailed in the implementation.
Description check ✅ Passed The PR description includes key sections (Goal, Implementation details, UI Changes with Figma link and screenshot, Testing) but is incomplete; several contributor and reviewer checklist items are unchecked, and a GIF is missing.

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

✨ Finishing touches
  • 📝 Generate docstrings

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: 5

🤖 Fix all issues with AI agents
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/AvatarPlaceholderUtils.kt`:
- Around line 26-40: The placeholder colors are stale because
rememberAvatarPlaceholderColors uses remember keyed only by identifier and
suppresses magic numbers; update it to include ChatTheme.colors in the remember
key (e.g., remember(identifier, ChatTheme.colors)) so theme changes invalidate
the cache, and replace the hardcoded when/number logic with a palette list
(List<Pair<Color,Color>>) (use identifier.hashCode().absoluteValue %
palette.size to pick the entry) so you can remove `@Suppress`("MagicNumber") and
avoid magic numbers.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/avatar/AvatarStack.kt`:
- Around line 61-69: The preview function AvatarStackPreview currently uses the
standard `@Preview`; replace that with the project's StreamPreview helper
annotation to follow guidelines: update the annotation on AvatarStackPreview to
`@StreamPreview` and keep the composable signature and body (users list, ChatTheme
and call to UserAvatarStack(overlap = 16.dp, users = users, size =
AvatarSize.Md)) unchanged so the preview behavior remains identical while
conforming to StreamPreview usage.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamColors.kt`:
- Around line 118-165: StreamColors KDoc is missing `@param` entries for the new
design-system color properties; update the StreamColors class KDoc to add `@param`
documentation for each new public parameter (accentError, accentNeutral,
accentSuccess, accentPrimary, avatarPaletteBg1..avatarPaletteBg5,
avatarPaletteText1..avatarPaletteText5, borderCoreImage, borderCoreOnDark,
borderCoreSurfaceSubtle, borderCorePrimary, textPrimary, stateBgDisabled,
stateTextDisabled, buttonStyleGhostBg, buttonStyleGhostBorder,
buttonStyleGhostTextPrimary, buttonStyleGhostTextSecondary,
buttonStyleOutlineBg, buttonStyleOutlineBorder, buttonStyleOutlineText,
buttonTypeDestructiveBg, buttonTypeDestructiveBorder, buttonTypeDestructiveText,
buttonTypeDestructiveTextInverse, buttonTypePrimaryBg,
buttonTypePrimaryBgDisabled, buttonTypePrimaryBorder, buttonTypePrimaryText,
buttonTypePrimaryTextDisabled, buttonTypeSecondaryTextDisabled, chatBgIncoming,
chatBgOutgoing, controlRemoveBg, controlRemoveBorder, controlRemoveIcon,
presenceBgOnline, presenceBgOffline, presenceBorder) describing purpose and
expected usage; ensure the KDoc sits above the StreamColors class declaration
(not as inline comments) and follows existing `@param` style/format used by other
documented parameters.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/StreamTypography.kt`:
- Around line 58-61: The class KDoc for StreamTypography is missing
documentation for the new public fields bodyEmphasis, captionEmphasis, and
metadataEmphasis; update the class-level KDoc parameter list to include brief
descriptions for each of these TextStyle properties (explain their intended
use/semantics and any distinctions between them), ensuring the param names match
exactly (bodyEmphasis, captionEmphasis, metadataEmphasis) and follow the
project's KDoc style for public API docs.
- Around line 145-159: The new emphasis TextStyles (bodyEmphasis,
captionEmphasis, metadataEmphasis) are missing the provided fontFamily and thus
ignore overrides; update each TextStyle in StreamTypography (the emphasis
entries shown) to include the fontFamily parameter passed into defaultTypography
(or the surrounding function/class that provides fontFamily) so the created
TextStyle sets fontFamily = fontFamily, preserving app-provided fonts and
consistent typography.
🧹 Nitpick comments (6)
.idea/codeStyles/Project.xml (1)

20-53: Ensure Java import layout aligns with any Spotless Java configuration if applicable.

The import layout configuration is valid and follows a sensible ordering (static imports first, grouped together; non-static imports separated by package group). Since the project uses Spotless for code style enforcement (per repository learnings), verify that this IDE configuration doesn't conflict with Spotless rules if Java files are also formatted by Spotless—otherwise developers may see constant reformatting on save vs. build.

The trailing <emptyLine /> on line 50 will add a blank line after the final import group, which is typically fine but worth confirming matches team preference.

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

217-223: Consider using @StreamPreview helper for the preview.

Per coding guidelines, Compose previews should use @StreamPreview helpers instead of the standard @Preview annotation.

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

153-181: Redundant modifiers on the Icon.

The Icon at lines 171-178 re-applies .background(background) and receives the outer modifier parameter, while its parent Box already sets the background and size. This is redundant and could cause visual issues if the passed modifier contains conflicting sizing/background.

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

183-202: Same redundancy in ChannelAvatarPlaceholder.

The Icon modifier re-applies .background(background) and the outer modifier, while the parent Box already handles background and sizing.

♻️ Suggested fix
     Box(
         modifier
             .background(background)
             .size(size.value),
         contentAlignment = Alignment.Center,
     ) {
         Icon(
             painter = painterResource(R.drawable.stream_compose_ic_team),
             contentDescription = null,
             tint = foreground,
-            modifier = modifier
-                .background(background)
-                .size(size.toPlaceholderIconSize()),
+            modifier = Modifier.size(size.toPlaceholderIconSize()),
         )
     }

218-259: Consider using @StreamPreview helper for the preview.

Per coding guidelines, Compose previews should use @StreamPreview helpers instead of the standard @Preview annotation.

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

174-176: Avoid @Suppress("LongMethod") unless it’s justified in the code.

Please either extract parts of the builders or add a short rationale comment near the suppression. As per coding guidelines, avoid suppressions unless documented.

Also applies to: 248-250

@github-actions
Copy link
Contributor

github-actions bot commented Jan 19, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.25 MB 5.25 MB 0.00 MB 🟢
stream-chat-android-offline 5.48 MB 5.48 MB 0.00 MB 🟢
stream-chat-android-ui-components 10.62 MB 10.61 MB -0.01 MB 🚀
stream-chat-android-compose 12.84 MB 11.70 MB -1.14 MB 🚀

@gpunto gpunto force-pushed the redesign/avatar branch 3 times, most recently from 8fde498 to 653cac1 Compare January 19, 2026 15:02
@gpunto gpunto marked this pull request as ready for review January 19, 2026 15:03
@gpunto gpunto requested a review from a team as a code owner January 19, 2026 15:03
@gpunto gpunto force-pushed the redesign/avatar branch 6 times, most recently from d2bedd9 to 1ff939c Compare January 19, 2026 17:01
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

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