Skip to content

Update SwipeToReplyIcon according new designs#6244

Open
VelikovPetar wants to merge 3 commits intov7from
redesing/update-swipetoreply-icon
Open

Update SwipeToReplyIcon according new designs#6244
VelikovPetar wants to merge 3 commits intov7from
redesing/update-swipetoreply-icon

Conversation

@VelikovPetar
Copy link
Contributor

@VelikovPetar VelikovPetar commented Mar 12, 2026

Goal

Update the SwipeToReply icon according design.

Implementation

Adds bubble background.

🎨 UI Changes

See snapshot tests.

Testing

Swipe to reply to see the new icon

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a dedicated swipe-to-reply icon component with improved visual design and interactive area optimization.
  • Tests

    • Added snapshot testing for the new swipe-to-reply icon component to ensure visual consistency.

@VelikovPetar VelikovPetar added the pr:improvement Improvement label Mar 12, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 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.

@VelikovPetar VelikovPetar changed the title Update SwipeToReplyIcon Update SwipeToReplyIcon according new designs Mar 12, 2026
@VelikovPetar VelikovPetar marked this pull request as ready for review March 12, 2026 13:50
@VelikovPetar VelikovPetar requested a review from a team as a code owner March 12, 2026 13:50
@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.25 MB 5.70 MB 0.45 MB 🟡
stream-chat-android-ui-components 10.60 MB 11.00 MB 0.40 MB 🟡
stream-chat-android-compose 12.81 MB 12.03 MB -0.78 MB 🚀

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Walkthrough

A new SwipeToReplyIcon composable UI component is introduced to render a styled reply button. The internal function is integrated into ChatComponentFactory to replace an inlined icon implementation, with the public API surface extended to include a singleton class for composable caching. Snapshot testing is added for the new component.

Changes

Cohort / File(s) Summary
SwipeToReplyIcon Component
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt, stream-chat-android-compose/api/stream-chat-android-compose.api
New internal composable function rendering a 32dp circular button with reply icon and theme styling; API surface expanded with auto-generated ComposableSingletons class for lambda caching.
Component Integration
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt
Refactored swipeToReplyContent to delegate to new SwipeToReplyIcon composable, removing inlined Icon implementation and associated Box wrapper.
Testing
stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIconTest.kt
New snapshot test using Paparazzi framework for SwipeToReplyIcon in dark mode Pixel 2 configuration.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

Hop and tap, swipe to reply with glee,
A circular button for all to see,
With a reply icon, shining bright,
Themed and tested, oh what a sight!
The SwipeToReplyIcon takes flight! 🐰

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

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.
Description check ❓ Inconclusive The description covers essential sections (Goal, Implementation, UI Changes, Testing) but lacks required elements like comparison screenshots, contributor checklist completion, and proper UI before/after visuals. Add before/after comparison screenshots or reference the specific snapshot test files. Complete the contributor checklist and clarify testing instructions with visual evidence.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: updating the SwipeToReplyIcon component according to new designs, which aligns with the changeset's primary objective.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch redesing/update-swipetoreply-icon
📝 Coding Plan for PR comments
  • Generate coding plan

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Around line 1777-1782: The new compiler-generated class
ComposableSingletons$SwipeToReplyIconKt is leaking into the public ABI because
the lambda/singleton was declared in a way that makes it public; make the
generated singleton/internal lambda non-public by moving the swipe-to-reply
composable and its helper lambda into a private/internal scope or annotating the
backing property with `@JvmSynthetic` or private visibility so it does not
generate a public top-level class. Concretely, locate the SwipeToReplyIcon
composable and the backing property/function referenced by lambda-1 and
getLambda-1$stream_chat_android_compose_release and change their declarations to
private/internal (or add `@JvmSynthetic` to the synthetic accessor) so the
compiler won’t emit the public ComposableSingletons$SwipeToReplyIconKt symbol.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt`:
- Around line 52-55: In SwipeToReplyIcon update the decorative Icon call (the
Icon using painterResource(R.drawable.stream_compose_ic_reply)) to use
contentDescription = null instead of an empty string so the accessibility node
is omitted; locate the Icon invocation in the SwipeToReplyIcon composable and
set its contentDescription to null (keeping tint and other params unchanged).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c873cdcd-fb68-490d-a141-30d638255306

📥 Commits

Reviewing files that changed from the base of the PR and between 6ccd8e1 and 646c26d.

⛔ Files ignored due to path filters (1)
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_SwipeToReplyIconTest_swipe_to_reply_icon.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • stream-chat-android-compose/api/stream-chat-android-compose.api
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIconTest.kt

Comment on lines +1777 to +1782
public final class io/getstream/chat/android/compose/ui/components/messages/ComposableSingletons$SwipeToReplyIconKt {
public static final field INSTANCE Lio/getstream/chat/android/compose/ui/components/messages/ComposableSingletons$SwipeToReplyIconKt;
public static field lambda-1 Lkotlin/jvm/functions/Function2;
public fun <init> ()V
public final fun getLambda-1$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function2;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid leaking the new Compose singleton into the public SDK ABI.

This adds ComposableSingletons$SwipeToReplyIconKt as a public type even though the PR only changes the icon’s visuals. That turns a compiler-generated implementation detail into supported API surface. Please adjust the source-level implementation so the new swipe-to-reply UI stays internal and the .api file does not gain this extra symbol.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@stream-chat-android-compose/api/stream-chat-android-compose.api` around lines
1777 - 1782, The new compiler-generated class
ComposableSingletons$SwipeToReplyIconKt is leaking into the public ABI because
the lambda/singleton was declared in a way that makes it public; make the
generated singleton/internal lambda non-public by moving the swipe-to-reply
composable and its helper lambda into a private/internal scope or annotating the
backing property with `@JvmSynthetic` or private visibility so it does not
generate a public top-level class. Concretely, locate the SwipeToReplyIcon
composable and the backing property/function referenced by lambda-1 and
getLambda-1$stream_chat_android_compose_release and change their declarations to
private/internal (or add `@JvmSynthetic` to the synthetic accessor) so the
compiler won’t emit the public ComposableSingletons$SwipeToReplyIconKt symbol.

Comment on lines +52 to +55
Icon(
painter = painterResource(R.drawable.stream_compose_ic_reply),
contentDescription = "",
tint = ChatTheme.colors.buttonSecondaryTextOnAccent,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the SwipeToReplyIcon.kt file
find . -name "SwipeToReplyIcon.kt" -type f | head -5

Repository: GetStream/stream-chat-android

Length of output: 193


🏁 Script executed:

# Once located, examine the specific lines mentioned (52-55)
cat -n stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt | sed -n '36,67p'

Repository: GetStream/stream-chat-android

Length of output: 1129


🌐 Web query:

Jetpack Compose Icon contentDescription null vs empty string accessibility semantics

💡 Result:

In Jetpack Compose, contentDescription has three distinct meanings:

  • contentDescription = nullabsent description. Compose won’t add a ContentDescription semantic for that Icon/Image, which is what you want for purely decorative graphics or when the parent already provides the label (common with semantics merging in clickable/material components). Android’s guidance explicitly calls out using null for decorative graphics. [1]

  • contentDescription = "" (empty string)present-but-empty description. This is not the same as null: you are still explicitly setting the semantic, just to an empty value. Compose API guidelines call this out directly: “null description is NOT the same as \"\" description” because null means “don’t add accessibility info”. [2] In practice, an empty description often leads to poor screen reader output (e.g., unlabeled/generic announcements) and can also interfere with merged labeling, so it’s rarely what you want.

  • Non-empty stringmeaningful label that TalkBack/screen readers can announce for an icon-only control (use localized strings). [1]

Rule of thumb: use null for decorative, use a real localized string for meaningful/actionable icons, and avoid "" unless you have a very specific reason to set an explicitly-empty content description. [1] [2]

Sources:
[1] Android Developers — API defaults (Compose accessibility) https://developer.android.com/develop/ui/compose/accessibility/api-defaults
[2] Compose component API guidelines (Git at Google) https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-component-api-guidelines.md


Use null for the decorative reply icon.

contentDescription = "" doesn't exclude the icon from accessibility; it creates a blank semantic entry. For decorative icons, use contentDescription = null to omit the accessibility node entirely.

Proposed fix
            Icon(
                painter = painterResource(R.drawable.stream_compose_ic_reply),
-                contentDescription = "",
+                contentDescription = null,
                tint = ChatTheme.colors.buttonSecondaryTextOnAccent,
            )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/SwipeToReplyIcon.kt`
around lines 52 - 55, In SwipeToReplyIcon update the decorative Icon call (the
Icon using painterResource(R.drawable.stream_compose_ic_reply)) to use
contentDescription = null instead of an empty string so the accessibility node
is omitted; locate the Icon invocation in the SwipeToReplyIcon composable and
set its contentDescription to null (keeping tint and other params unchanged).

@sonarqubecloud
Copy link

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

Labels

pr:improvement Improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants