Improve message list TalkBack accessibility#6440
Conversation
Message rows previously announced as "Message item, …" with the sender
name silently hidden from TalkBack and no action labels on the row's
clickable, so users heard the generic "double-tap to activate" hint with
no verb and could not tell who sent an incoming message in a group or
thread.
Push the a11y content down to the leaves so Compose's natural merge
composes them:
- `MessageFooter` sender name dropped its `clearAndSetSemantics { testTag
= … }` wrapper, which had been wiping the Text's natural `text`
semantic. Replaced with `Modifier.testTag(…)` so the testTag survives
and the user name is announced.
- `MessageContainer` dropped the static "Message item" placeholder
`contentDescription` on the outer Row. `combinedClickable` gains
`onClickLabel = "Open thread"` (when `canOpenThread`) and
`onLongClickLabel = "Show message options"` (when `canOpenActions`),
each gated to the actions that actually fire.
Adds the two new strings across all 7 supported locales and drops the
now-unused `stream_compose_cd_message_item` placeholder from all 8
locales.
The date and unread separators in the message list are visual landmarks
that screen-reader users need to skim a long conversation, but neither
exposed a `heading()` semantic, so TalkBack's swipe-by-heading gesture
skipped them. The unread separator also rendered "1 unread messages"
because its label was a `<string>` with no plural form.
Add `Modifier.semantics { heading() }` to both the date separator
(`DefaultMessageDateSeparatorContent`) and the unread separator
(`DefaultMessageUnreadSeparatorContent`).
Convert `stream_compose_message_list_unread_separator` from `<string>`
to `<plurals>` across all 8 locales so n=1 reads as a singular ("1
unread message") and n>1 keeps the plural. Update the caller to use
`pluralStringResource`.
The typing indicator in the message list shows avatars and animated dots
but no text, so TalkBack picked nothing up — it neither focused the
bubble nor announced when someone started typing.
Wrap the indicator's outer Row in a polite live region with a localized
description ("X is typing" / "X and Y are typing" / "N people are
typing", reusing the existing `stream_compose_channel_list_typing_*`
strings since the wording is identical), and merge descendants so the
bubble announces as a single unit. The description-building logic is
extracted to a small private helper to keep the composable under
detekt's method-length cap.
The reaction toggles in the long-press reactions picker rendered a
checked background to indicate the user's own reactions, but exposed
nothing to TalkBack — no role, no selected state, just "double-tap to
activate". A user could not tell which reactions they had already
chosen. In-bubble reactions had a similar gap: each chip's clickable
had no `onClickLabel`, so TalkBack announced the generic "double-tap to
activate" with no verb.
- `ReactionToggle` swaps `Modifier.clickable { onChange(!checked) }` for
`Modifier.toggleable(value = checked, role = Role.Switch,
onValueChange = onChange)`. TalkBack now announces the emoji plus
"switch, on / off, double-tap to toggle".
- `MessageReactions` adds `onClickLabel = "Show reactions"` to both the
`ClusteredMessageReactions` row clickable and the per-chip
`ReactionChip` clickable, so focusing a chip says "<emoji>, double
tap to Show reactions".
Adds `stream_compose_message_reactions_show` across the 7 supported
locales. No public API surface change.
Image, video, file and link attachments in the message list previously announced as "double-tap to activate" — generic, no verb. The `combinedClickable` on each of those attachment containers had no `onClickLabel`, so TalkBack fell back to the platform default. Add `onClickLabel = "Open attachment"` to `MediaAttachmentContent`, `FileAttachmentContent`, and `LinkAttachmentContent`. TalkBack now reads "<type> attachment, double tap to Open attachment" for images and videos, and "<filename>, <size>, double tap to Open attachment" for files (the inner Texts already carry the name and size). Adds `stream_compose_message_attachment_open` across the 7 supported locales. No public API surface change. Poll, location, giphy and audio attachments are left for a follow-up — each has its own composable and a different interaction model. Multi- attachment disambiguation (e.g. "Image 1 of 4") is also a separate follow-up; it needs index/total plumbing through the multi-attachment grid.
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
|
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (16)
WalkthroughThe PR systematically enhances accessibility across message UI components by introducing localized click labels for attachments and reactions, replacing manual semantic descriptions with modular label parameters, supporting pluralized unread message counts across locales, and refactoring the reaction toggle to use proper Compose toggle semantics with role support. ChangesMessage Accessibility and Interaction Enhancements
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |



Goal
Resolve TalkBack accessibility gaps on the Compose message list (channel screen, threads screen). Issues a screen-reader user hits today:
clearAndSetSemanticswrapper kept only the testTag), and tap/long-press hints have no verb.n = 1(no<plurals>).Implementation
Five self-contained commits, each scoped to one concern:
Make message rows accessible to TalkBack— drop the static "Message item" placeholder on the outerRow;combinedClickablegainsonClickLabel = "Open thread"(whencanOpenThread) andonLongClickLabel = "Show message options"(whencanOpenActions).MessageFootersender-nameTextdrops its destructiveclearAndSetSemantics { testTag = … }forModifier.testTag(…)so the user name is spoken again. Drops the orphanedstream_compose_cd_message_itemplaceholder across all 8 locales.Make message list separators accessible as headings— addModifier.semantics { heading() }to both the date and unread separators inDefaultMessageDateSeparatorContent/DefaultMessageUnreadSeparatorContent. Convertstream_compose_message_list_unread_separatorfrom<string>to<plurals>across all 8 locales so n=1 reads as a singular.Announce typing indicator to TalkBack— wrap the indicator row in a polite live region with a localized description ("X is typing" / "X and Y are typing" / "N people are typing", reusing the existingstream_compose_channel_list_typing_*strings). The description is built by a small private helper to keep the composable under the method-length cap.Announce reaction state to TalkBack—ReactionToggle(the picker tile) swapsModifier.clickable { onChange(!checked) }forModifier.toggleable(value = checked, role = Role.Switch, onValueChange = onChange)so TalkBack announces the emoji plus "switch, on / off, double-tap to toggle". In-bubble reactions getonClickLabel = "Show reactions"on bothClusteredMessageReactionsand per-chipReactionChipclickables.Label message attachment tap action for TalkBack— addonClickLabel = "Open attachment"to thecombinedClickableonMediaAttachmentContent,FileAttachmentContent, andLinkAttachmentContent.All four new strings (
stream_compose_message_item_open_thread,stream_compose_message_item_options,stream_compose_message_reactions_show,stream_compose_message_attachment_open) ship with translations for the 7 supported locales (es, fr, hi, in, it, ja, ko). No public API surface changes (apiDump clean).Testing
Manual steps on the Compose sample with TalkBack ON and Settings → Accessibility → TalkBack → Verbosity → Speak usage hints enabled. Open any group channel with a mix of messages.
Summary by CodeRabbit
New Features
Localization
Improvements