Skip to content

fix: a11y continuous improvements#3632

Open
isekovanic wants to merge 9 commits into
developfrom
fix/a11y-fixes
Open

fix: a11y continuous improvements#3632
isekovanic wants to merge 9 commits into
developfrom
fix/a11y-fixes

Conversation

@isekovanic
Copy link
Copy Markdown
Contributor

@isekovanic isekovanic commented Jun 6, 2026

🎯 Goal

Cross platform a11y fixes across the message surface (message row, footer, reactions, replies) and the channel preview list. VoiceOver / TalkBack now read each surface with proper labels, no misleading affordances, and correct focus behavior.

🛠 Implementation details

  • Poll message rotor actions - iOS announced custom rotor actions that couldn't actually be activated. Removed the composite rotor; poll bubbles now drill in so each option is a focus stop with proper radio/checkbox role.
  • Reply composer focus - initiating a reply landed VoiceOver focus on the navigation back button. Reply now focuses the composer's text input when a screen reader is active, and announces "Replying to {user}" + "Editing message" via useAnnounceOnShow so the user knows the composer entered reply/edit mode.
  • Channel preview verbosity - list rows previously announced "Avatar of X" per member, bare timestamps ("12:14 AM"), bare unread counts ("3"). Each leaf now carries a curated label: avatar reads "Direct chat with {name}" / "Channel with N members", date reads "Last message {date}", unread badge reads "{count} unread messages", muted indicator reads "Muted", delivery-status icon reads "Read, sent by you" / "Delivered, sent by you" / etc.
  • Channel preview delivery status not read - the status View had accessibilityLabel but no accessible={true}, so VO walked past it. Fixed by adding accessible so the composed delivery-status label is
    announced.
  • Message footer delivery state silent - the checkmark icon was a silent SVG; VO read only "11:05 AM". Footer is now accessible + accessibilityRole='text' (cross-platform compose), with MessageStatus
    rendering a HiddenA11yText for the localized status string. Footer announces as one stop: "Read, 11:05 AM".
  • Reaction list "actions available" misleading affordance — VO promised rotor actions that didn't exist. Clustered reactions are now one labeled button via the Pressable's auto compose (emoji names + "you reacted" tag for own + "and N more reactions" suffix), with hint "Double tap to view reactions". Segmented reactions stay as per-item Pressables with the same "you reacted" tagging.
  • Message rich content can't be activated - message rows with images, files, quoted replies, or shared location couldn't drill into the inner content. Generalized the poll only accessible={false} to cover any interactive children (attachments, quoted_message, poll, shared_location). Plain text messages keep their single focus stop behavior; rich messages drill in.

New shared components

  • CompositeAccessibilityProbe (package/src/components/Accessibility/) - wraps non Text visual content (avatars, icons, badges) so it announces as one focus stop with a curated label. Internally renders a hidden Text sibling + a decorative marked View around children. Used by ChannelAvatar, ChannelPreviewMutedStatus, ChannelMessagePreviewDeliveryStatus. Solves the iOS vs Android composition asymmetry where Android's importantForAccessibility='no-hide-descendants' leaks through nested accessible={true} descendants.
  • HiddenA11yText (package/src/components/Accessibility/) - visually invisible Text whose only job is to splice extra info into a parent's compose loop (e.g. "you reacted", "and N more reactions", localized delivery status). Different concern from the probe - this is for adding text to a composition chain, not for collapsing a subtree into one stop.

Both are exported from the SDK so consumers building their own custom message / preview UIs can reuse the patterns.

🎨 UI Changes

iOS
Before After
Android
Before After

🧪 Testing

☑️ Checklist

  • I have signed the Stream CLA (required)
  • PR targets the develop branch
  • Documentation is updated
  • New code is tested in main example apps, including all possible scenarios
    • SampleApp iOS and Android
    • Expo iOS and Android

@isekovanic isekovanic requested review from oliverlaz and szuperaz June 6, 2026 04:37
@Stream-SDK-Bot
Copy link
Copy Markdown
Contributor

Stream-SDK-Bot commented Jun 6, 2026

SDK Size

title develop branch diff status
js_bundle_size 1725 KB 1727 KB +2373 B 🔴

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