Skip to content

Improve compose TalkBack screen-entry announcements#6467

Merged
andremion merged 4 commits into
developfrom
fix/compose-talkback-screen-announcements
May 25, 2026
Merged

Improve compose TalkBack screen-entry announcements#6467
andremion merged 4 commits into
developfrom
fix/compose-talkback-screen-announcements

Conversation

@andremion
Copy link
Copy Markdown
Contributor

@andremion andremion commented May 22, 2026

AND-1180

Goal

TalkBack was reading the wrong thing whenever a user navigated between screens in the Compose sample, and was silent when sub-screens appeared inside an existing Activity:

  • In the sample app, every Activity entry announced "Chat Sample Compose" (the application label) because most activities had no per-activity android:label. The user couldn't tell which screen they had just landed on.
  • In the Compose SDK, screens shown via FullscreenDialog (e.g. AddMembersScreen, GroupChannelEditScreen reached from GroupChannelInfoScreen) had no Modifier.semantics { paneTitle = ... }, so TalkBack made no pane-change announcement on dialog open. The user heard only the back-button focus, with no indication of which dialog had appeared.
  • Top-level Screen composables (ChannelsScreen, ChatsScreen, ThreadsScreen, DirectChannelInfoScreen, GroupChannelInfoScreen) had no paneTitle either. When used as a pane in an adaptive layout or shown via a Compose Navigation route inside an existing Activity, pane changes were silent.

The two mechanisms are independent and not interchangeable. android:label is the only thing TalkBack announces on Activity entry. paneTitle is the only thing TalkBack announces on in-Activity pane / dialog changes. Empirically verified: removing android:label while setting paneTitle alone on PinnedMessagesActivity produced "Chat Sample Compose, Back, button…" — paneTitle does not fire on initial Activity entry. Confirmed by the official Compose semantics docs: "Window-like custom components, similar to ModalBottomSheet, need additional signals to differentiate them from surrounding content. For this, you can use paneTitle semantics, so that any relevant window or pane changes may be represented appropriately by the accessibility services."

Implementation

Compose sample app — per-Activity android:label

Added android:label to 13 activities in stream-chat-android-compose-sample/src/main/AndroidManifest.xml that previously had none (two attachment activities — Files, Media — already carried a label). StartupActivity is deliberately skipped because it routes to another Activity in onCreate and never gains stable focus. Labels reuse existing sample strings (pinned_messages_title, reminders_title, add_channel_title, etc.) or SDK ui-common strings (stream_ui_channel_info_contact_title, stream_ui_channel_info_group_title) where they fit. Only two net-new sample strings were needed (channel_title, user_profile_title) for screens whose top bar is dynamic or empty.

Compose SDK — paneTitle on Screen composables

Added Modifier.semantics { paneTitle = ... } to seven SDK Screen composables. All reuse existing strings or the screen's existing title parameter — no new public API:

Screen paneTitle source
AddMembersScreen R.string.stream_compose_add_members_title
GroupChannelEditScreen UiCommonR.string.stream_ui_channel_info_edit_title
DirectChannelInfoScreen UiCommonR.string.stream_ui_channel_info_contact_title
GroupChannelInfoScreen UiCommonR.string.stream_ui_channel_info_group_title
ChannelsScreen existing title parameter
ChatsScreen existing title parameter (applied on the list-pane Scaffold)
ThreadsScreen existing title parameter

ChannelScreen (dynamic channel-name title) and MediaGalleryPreviewScreen (complex dual-overload structure) are deferred to follow-up PRs — each needs its own design decision.

ChannelsScreen, ChatsScreen, and ThreadsScreen also have their @param title KDoc updated to state that the value drives the paneTitle semantic.

No visual changes; only accessibility semantics and manifest labels.

Testing

  1. Enable TalkBack.
  2. Compose sample — Activity labels. Launch the sample app and navigate through each screen, listening to the announcement on entry:
    • Welcome / login → "Welcome to Stream Chat" / "Advanced options".
    • Channel list → "Chats".
    • Open a channel → "Channel".
    • From the channel header, open channel info → "Contact Info" (DM) or "Group Info" (group).
    • From channel info → Pinned Messages → "Pinned Messages".
    • From the navigation drawer → New chat → "New Chat"; New group chat → "Add group members"; Reminders → "Message Reminders"; Profile → "Profile".
    • From a message → media gallery → existing labels ("Photos & Videos" / "Files").
    • On each, confirm the announced label matches the table above and that "Chat Sample Compose" is no longer heard.
  3. Compose SDK — paneTitle for FullscreenDialog content. Open a group channel's info screen, tap Add Members → TalkBack should announce "Add Members" when the dialog appears. From the same screen, tap the edit action → TalkBack should announce "Edit".
  4. Compose SDK — Adaptive layout. In the sample app, enable the "Adaptive layout (Experimental)" toggle in Custom settings and log in. As you navigate between the list and detail panes, the active pane should be announced ("Stream Chat" / channel name).

Summary by CodeRabbit

  • Improvements
    • Added proper activity titles throughout the app for clearer navigation and task switching.
    • Enhanced accessibility support with improved screen reader annotations across messaging and channel management screens.

Review Change Stack

@andremion andremion requested a review from a team as a code owner May 22, 2026 15:55
@andremion
Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 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, or the PR is bot-authored.
  • An issue is linked (Linear ticket or GitHub issue), or the PR is bot-authored.

🎉 Great job! This PR is ready for review.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 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.

@andremion andremion added the pr:improvement Improvement label May 22, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Walkthrough

This PR adds Compose accessibility semantics (paneTitle) to multiple chat and channel screens, improving screen reader announcements. Activity declarations and string resources are updated in the manifest and string files to provide labels for activities and localized pane titles.

Changes

Accessibility Pane Title Support

Layer / File(s) Summary
Manifest activity labels and string resources
stream-chat-android-compose-sample/src/main/AndroidManifest.xml, stream-chat-android-compose-sample/src/main/res/values/strings.xml
Ten existing activity declarations are expanded with explicit android:label attributes, and MessageRemindersActivity and UserProfileActivity are converted from shorthand to full activity elements. Two new string resources (channel_title, user_profile_title) are added to support the labels and accessibility strings.
Channel info screen accessibility semantics
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channel/info/AddMembersScreen.kt, DirectChannelInfoScreen.kt, GroupChannelEditScreen.kt, GroupChannelInfoScreen.kt
Four channel info screens import Compose semantics APIs and apply semantics { paneTitle = ... } modifiers to their root composables, setting localized pane titles for TalkBack and other accessibility tools.
List and navigation screen accessibility semantics
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/ChannelsScreen.kt, chats/ChatsScreen.kt, threads/ThreadsScreen.kt
Three pane-based screens import semantics APIs, update KDoc to document that the title parameter drives the paneTitle semantic, and apply semantics { paneTitle = title } modifiers. The Chats screen includes the title in its remember dependency to ensure semantics stay in sync when the title changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

pr:improvement

Suggested reviewers

  • gpunto

Poem

🐰 A coat of care for screens and sight,
Pane titles now announced just right,
Labels added, semantics blessed,
Each accessibility request addressed.
From info screens to chats so bright,
All readers find their bearings right! 🎯

🚥 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 directly addresses the main change: adding TalkBack screen-entry announcements to Compose screens, which is the core purpose of the PR.
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.
Description check ✅ Passed PR description is comprehensive and well-structured, covering goal, implementation details, testing steps, and a detailed explanation of the accessibility problem and solution.

✏️ 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 fix/compose-talkback-screen-announcements

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.

@andremion andremion enabled auto-merge (squash) May 22, 2026 15:59
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.82 MB 5.82 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.02 MB 11.02 MB 0.00 MB 🟢
stream-chat-android-compose 12.42 MB 12.42 MB 0.00 MB 🟢

andremion added 4 commits May 25, 2026 09:43
TalkBack announces android:label on Activity entry. Without per-activity labels, every screen was announced as 'Chat Sample Compose'. Each non-routing activity now has a screen-specific label, reusing existing sample/SDK strings where they fit; only 'channel_title' and 'user_profile_title' are new keys.
paneTitle is the Compose semantic that drives TalkBack's pane-change announcement (TYPE_WINDOW_STATE_CHANGED) when a screen appears via FullscreenDialog, adaptive-layout pane swap, or Compose Navigation route change inside an existing Activity. Without it, TalkBack only announces the host Activity's android:label on entry and stays silent on subsequent in-Activity pane changes.

- AddMembersScreen, GroupChannelEditScreen: announce 'Add Members' / 'Edit' when shown via FullscreenDialog from GroupChannelInfoScreen.
- DirectChannelInfoScreen, GroupChannelInfoScreen, ChannelsScreen, ChatsScreen, ThreadsScreen: announce their title when used as a pane in an adaptive layout or routed-to via Compose Navigation. All reuse existing strings or the screen's existing title parameter; no new public API.
ChannelsScreen, ChatsScreen, and ThreadsScreen route their title parameter into Modifier.semantics { paneTitle = ... } on the screen root. The @param title KDoc now states that contract so integrators know the value is announced by TalkBack when the screen appears as a pane.
ThreadsScreenTest is a new Robolectric Compose UI test class that follows the ChannelsScreenTest / ChatsScreenTest pattern: mocks the chat client + state, renders the screen with default and custom titles, asserts the header text. ChatsScreenTest gains an equivalent custom-title case so the new remember(listContentMode, title) key path is exercised.
@andremion andremion force-pushed the fix/compose-talkback-screen-announcements branch from 4431862 to 3f5094e Compare May 25, 2026 08:45
@sonarqubecloud
Copy link
Copy Markdown

@andremion andremion merged commit 68ec437 into develop May 25, 2026
21 of 22 checks passed
@andremion andremion deleted the fix/compose-talkback-screen-announcements branch May 25, 2026 13:12
gpunto pushed a commit that referenced this pull request May 27, 2026
* Add android:label to compose sample activities for TalkBack

TalkBack announces android:label on Activity entry. Without per-activity labels, every screen was announced as 'Chat Sample Compose'. Each non-routing activity now has a screen-specific label, reusing existing sample/SDK strings where they fit; only 'channel_title' and 'user_profile_title' are new keys.

* Add paneTitle to compose SDK screens for TalkBack pane announcements

paneTitle is the Compose semantic that drives TalkBack's pane-change announcement (TYPE_WINDOW_STATE_CHANGED) when a screen appears via FullscreenDialog, adaptive-layout pane swap, or Compose Navigation route change inside an existing Activity. Without it, TalkBack only announces the host Activity's android:label on entry and stays silent on subsequent in-Activity pane changes.

- AddMembersScreen, GroupChannelEditScreen: announce 'Add Members' / 'Edit' when shown via FullscreenDialog from GroupChannelInfoScreen.
- DirectChannelInfoScreen, GroupChannelInfoScreen, ChannelsScreen, ChatsScreen, ThreadsScreen: announce their title when used as a pane in an adaptive layout or routed-to via Compose Navigation. All reuse existing strings or the screen's existing title parameter; no new public API.

* Document paneTitle behavior on title @param of public screen composables

ChannelsScreen, ChatsScreen, and ThreadsScreen route their title parameter into Modifier.semantics { paneTitle = ... } on the screen root. The @param title KDoc now states that contract so integrators know the value is announced by TalkBack when the screen appears as a pane.
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