Commit 5e38683
authored
Composer attachment picker accessibility improvements (#6404)
* Announce composer attachments button as Open/Close based on picker visibility
The attachments toggle button in the message composer announced as
"Attachments, double tap to activate" in both states, which is misleading
when the picker is already open and tapping closes it. Switch to a
state-aware content description: "Open attachments" when the picker is
hidden, "Close attachments" when it is shown.
Removes the now-unused stream_compose_attachments string from all
locales; the new strings live under the stream_compose_message_composer_*
namespace alongside other composer button labels.
* Apply trailing comma to MessageComposerLeadingContent
* Use Tab semantics on attachment picker tabs
The picker tabs (Media, Camera, Files, Polls, Commands) used a
FilledIconToggleButton, which emits Role.Checkbox + a toggleable state.
TalkBack announced an active tab as "Checked, Media, checkbox, double tap
to toggle" — wrong role and a misleading action hint.
Override the per-tab semantics with semantics(mergeDescendants = true) to
declare Role.Tab + selected, while keeping the underlying focusable /
focused / clickable semantics intact so the tab stays discoverable to
accessibility services. Role.Tab takes precedence over the lingering
ToggleableState in TalkBack's announcement, so the active tab now
announces as "Media, tab, selected".
* Make attachment picker grid items announceable to TalkBack
The image/video grid items in the attachment picker had no
contentDescription, no role, and no selected state in the accessibility
tree. TalkBack focused them silently, leaving users unable to identify
or select photos or videos.
Add merged semantics on each item (contentDescription "Photo" or
"Video", Role.Button, selected = isSelected, plus the existing testTag)
and mark the decorative RadioCheck and VideoBadge overlays as
non-semantic with clearAndSetSemantics so they no longer announce
phantom checkbox state. Translations added for the 7 supported locales.
* Override file picker item action hint to "select"
TalkBack announced "Double tap to activate" for file items in the picker,
which is misleading because tapping selects the file for attachment, not
activates it.
Add merged semantics on each file row with Role.Button, the current
selected state, and an onClick action labelled "select" so TalkBack now
announces "Double tap to select". Mark the decorative RadioCheck and
RadioButton indicators with clearAndSetSemantics so they no longer
contribute phantom toggle/radio state to the merged announcement.
Translations added for the 7 supported locales.
* Announce composer attachment chip cancel icon as "Remove attachment"
The "x" button on each composer attachment chip announced as "Cancel" —
misleading because the button removes a specific attachment from the
message, not abandons an unrelated action.
Add an optional contentDescription parameter to ComposerCancelIcon
(defaulted to the existing stream_compose_cancel for backwards
compatibility) and pass "Remove attachment" from the three composer
attachment chip call sites: media, file, and audio recording. Other
ComposerCancelIcon usages (edit indicator, quoted message, link
preview) keep the original "Cancel" label since they aren't attachment
chips. Translations added for the 7 supported locales.
* Announce attachment add and remove via composer live region
Tapping a thumbnail to add an attachment, or capturing a photo via the
camera tab, played only a brief system sound and made no TalkBack
announcement, leaving users without confirmation that the attachment
was added. Removing an attachment was equally silent.
Add an internal MessageComposerLiveRegion composable that mounts inside
the composer's root column (always present) and watches attachment list
size. On size increase it announces the type of the latest attachment
("Photo attached", "Video attached", "Audio recording attached", or
"File attached"); on size decrease it announces "Attachment removed".
The text is hosted in a hidden Text marked with LiveRegionMode.Polite +
invisibleToUser, so it is not navigable but is announced when its value
changes. Translations added for the 7 supported locales.
Camera capture flows through the same composer state, so the same live
region also confirms photo capture without further wiring.
* Switch attachment picker action hint to "remove" when item is selected
When a picker item is already selected, double-tapping toggles it off
rather than selecting it. The action hint should reflect that — TalkBack
should announce "double tap to remove" for already-selected items, and
"double tap to select" for not-yet-selected items.
Branch the onClick semantic action label on the item's selected state in
both the image grid (DefaultImagesPickerItem) and the file list row
(DefaultFilesPickerItem). Translations added for the 7 supported locales.
* Announce CreatePoll sheet title before the auto-focused input
When the Create Poll sheet opened, TalkBack jumped straight to
announcing the IME and the auto-focused Question field, never
mentioning the screen the user had just entered.
Mark the "Create Poll" title in PollCreationHeader as a heading and add
a paneTitle semantic property on the screen root so accessibility
services announce the new pane on entry.
* Refine attachment picker accessibility per TalkBack verification
Real-device TalkBack testing surfaced three adjustments to the original
audit fixes:
- Composer +/× button: hearing "Close attachments" right after opening
the picker reads backwards. Switch to the standard expandable-button
pattern — contentDescription stays as "Attachments" + stateDescription
"collapsed" / "expanded". Add paneTitle on the picker root so the new
pane is announced on entry.
- Picker tabs leaked the underlying ToggleableState ("checked") through
semantics(mergeDescendants = true). Switch to clearAndSetSemantics so
only Role.Tab + selected reach TalkBack.
- The Compose liveRegion semantic on a hidden Text never fired —
TalkBack skips zero-size / transparent nodes. Switch to
View.announceForAccessibility() via LocalView. Rename the composable
to MessageComposerAttachmentAnnouncer.
.com>
* Pass onClickLabel via clickable instead of duplicate semantics action
Move the picker item's accessibility click label from a duplicated
`semantics { onClick(label = …) }` block onto `Modifier.clickable`'s
`onClickLabel` parameter, removing the order dependency between the
two modifiers.
* Cover composer attachment announcer's type-resolution branches
Extract `announceAddedAttachment` to `internal` (annotated `@VisibleForTesting`)
and add a JVM unit test exercising the image / video / audio recording / file /
null branches.
* Use hideFromAccessibility() for decorative attachment-picker children
Replaces empty-block clearAndSetSemantics {} on the picker checkmark/radio
icons, the video duration badge, and the file-type label with the more
intent-revealing semantics { hideFromAccessibility() }. Non-empty
clearAndSetSemantics {…} sites that replace semantics with a clean set are
left as-is — hideFromAccessibility() would hide the node entirely.1 parent 41a2304 commit 5e38683
25 files changed
Lines changed: 416 additions & 24 deletions
File tree
- stream-chat-android-compose
- api
- src
- main
- java/io/getstream/chat/android/compose/ui
- components
- attachments
- files
- images
- composer
- messages
- attachments
- poll
- composer/internal
- attachments
- util
- res
- values-es
- values-fr
- values-hi
- values-in
- values-it
- values-ja
- values-ko
- values
- test/kotlin/io/getstream/chat/android/compose/ui/components/composer
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1062 | 1062 | | |
1063 | 1063 | | |
1064 | 1064 | | |
1065 | | - | |
| 1065 | + | |
1066 | 1066 | | |
1067 | 1067 | | |
1068 | 1068 | | |
| |||
Lines changed: 3 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
39 | 40 | | |
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
43 | 44 | | |
| 45 | + | |
44 | 46 | | |
45 | 47 | | |
46 | 48 | | |
| |||
53 | 55 | | |
54 | 56 | | |
55 | 57 | | |
56 | | - | |
| 58 | + | |
57 | 59 | | |
58 | 60 | | |
59 | 61 | | |
| |||
Lines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
| 34 | + | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
59 | 60 | | |
60 | 61 | | |
61 | 62 | | |
62 | | - | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
Lines changed: 19 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
37 | 42 | | |
38 | 43 | | |
39 | 44 | | |
| |||
126 | 131 | | |
127 | 132 | | |
128 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
129 | 141 | | |
130 | 142 | | |
131 | 143 | | |
132 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
133 | 149 | | |
134 | 150 | | |
135 | 151 | | |
| |||
158 | 174 | | |
159 | 175 | | |
160 | 176 | | |
| 177 | + | |
161 | 178 | | |
162 | 179 | | |
163 | 180 | | |
164 | 181 | | |
165 | 182 | | |
| 183 | + | |
166 | 184 | | |
167 | 185 | | |
168 | 186 | | |
| |||
Lines changed: 34 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
41 | 48 | | |
42 | 49 | | |
43 | 50 | | |
| |||
107 | 114 | | |
108 | 115 | | |
109 | 116 | | |
| 117 | + | |
110 | 118 | | |
111 | 119 | | |
112 | 120 | | |
| |||
125 | 133 | | |
126 | 134 | | |
127 | 135 | | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
128 | 151 | | |
129 | 152 | | |
130 | 153 | | |
131 | 154 | | |
132 | | - | |
133 | | - | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
134 | 162 | | |
135 | 163 | | |
136 | 164 | | |
| |||
142 | 170 | | |
143 | 171 | | |
144 | 172 | | |
145 | | - | |
| 173 | + | |
| 174 | + | |
146 | 175 | | |
147 | 176 | | |
148 | 177 | | |
| |||
152 | 181 | | |
153 | 182 | | |
154 | 183 | | |
155 | | - | |
| 184 | + | |
| 185 | + | |
156 | 186 | | |
157 | 187 | | |
158 | 188 | | |
| |||
Lines changed: 85 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
| 119 | + | |
| 120 | + | |
119 | 121 | | |
120 | 122 | | |
121 | 123 | | |
| |||
Lines changed: 7 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
30 | 33 | | |
31 | 34 | | |
32 | 35 | | |
| |||
109 | 112 | | |
110 | 113 | | |
111 | 114 | | |
| 115 | + | |
112 | 116 | | |
113 | | - | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
114 | 120 | | |
115 | 121 | | |
116 | 122 | | |
| |||
Lines changed: 21 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
38 | 45 | | |
39 | 46 | | |
40 | 47 | | |
| |||
132 | 139 | | |
133 | 140 | | |
134 | 141 | | |
| 142 | + | |
135 | 143 | | |
136 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
137 | 156 | | |
138 | 157 | | |
139 | 158 | | |
| |||
144 | 163 | | |
145 | 164 | | |
146 | 165 | | |
147 | | - | |
148 | 166 | | |
149 | | - | |
| 167 | + | |
150 | 168 | | |
151 | 169 | | |
152 | 170 | | |
| |||
Lines changed: 7 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
| 44 | + | |
41 | 45 | | |
42 | 46 | | |
43 | 47 | | |
| |||
73 | 77 | | |
74 | 78 | | |
75 | 79 | | |
| 80 | + | |
76 | 81 | | |
77 | 82 | | |
78 | 83 | | |
79 | | - | |
| 84 | + | |
| 85 | + | |
80 | 86 | | |
81 | 87 | | |
82 | 88 | | |
| |||
0 commit comments