Skip to content

Commit 1ab8c4b

Browse files
authored
Improve poll vote row TalkBack accessibility (#6461)
* Make poll vote rows TalkBack-navigable with merged content * Announce poll vote count with units for TalkBack
1 parent acf931d commit 1ab8c4b

1 file changed

Lines changed: 38 additions & 11 deletions

File tree

  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/PollMessageContent.kt

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import androidx.compose.foundation.layout.height
2929
import androidx.compose.foundation.layout.heightIn
3030
import androidx.compose.foundation.layout.padding
3131
import androidx.compose.foundation.layout.size
32+
import androidx.compose.foundation.selection.toggleable
3233
import androidx.compose.foundation.shape.RoundedCornerShape
3334
import androidx.compose.material3.AlertDialog
3435
import androidx.compose.material3.ButtonDefaults
@@ -50,6 +51,11 @@ import androidx.compose.ui.graphics.StrokeCap
5051
import androidx.compose.ui.platform.LocalContext
5152
import androidx.compose.ui.res.pluralStringResource
5253
import androidx.compose.ui.res.stringResource
54+
import androidx.compose.ui.semantics.Role
55+
import androidx.compose.ui.semantics.clearAndSetSemantics
56+
import androidx.compose.ui.semantics.contentDescription
57+
import androidx.compose.ui.semantics.hideFromAccessibility
58+
import androidx.compose.ui.semantics.semantics
5359
import androidx.compose.ui.text.style.TextOverflow
5460
import androidx.compose.ui.tooling.preview.Preview
5561
import androidx.compose.ui.unit.dp
@@ -69,6 +75,7 @@ import io.getstream.chat.android.compose.ui.theme.MessageFailedIconParams
6975
import io.getstream.chat.android.compose.ui.theme.MessageStyling
7076
import io.getstream.chat.android.compose.ui.theme.MessageStyling.PollStyle
7177
import io.getstream.chat.android.compose.ui.theme.StreamTokens
78+
import io.getstream.chat.android.compose.ui.util.applyIf
7279
import io.getstream.chat.android.compose.ui.util.isErrorOrFailed
7380
import io.getstream.chat.android.compose.ui.util.passiveRipple
7481
import io.getstream.chat.android.compose.util.extensions.toSet
@@ -427,23 +434,35 @@ private fun PollOptionItem(
427434
onRemoveVote: () -> Unit,
428435
) {
429436
val typography = ChatTheme.typography
437+
val toggleRole = if (poll.maxVotesAllowed == 1) Role.RadioButton else Role.Checkbox
438+
val onToggle: (Boolean) -> Unit = { enabled ->
439+
val canVote = poll.maxVotesAllowed?.let { checkedCount < it } ?: true
440+
if (enabled && canVote && !checked) {
441+
onCastVote.invoke()
442+
} else if (!enabled) {
443+
onRemoveVote.invoke()
444+
}
445+
}
430446

431447
Row(
432-
modifier = modifier.fillMaxWidth(),
448+
modifier = modifier
449+
.fillMaxWidth()
450+
.applyIf(!poll.closed) {
451+
toggleable(
452+
value = checked,
453+
role = toggleRole,
454+
onValueChange = onToggle,
455+
)
456+
}
457+
.semantics(mergeDescendants = true) {},
433458
horizontalArrangement = Arrangement.spacedBy(StreamTokens.spacingSm),
434459
verticalAlignment = Alignment.CenterVertically,
435460
) {
436461
if (!poll.closed) {
437462
RadioCheck(
463+
modifier = Modifier.semantics { hideFromAccessibility() },
438464
checked = checked,
439-
onCheckedChange = { enabled: Boolean ->
440-
val canVote = poll.maxVotesAllowed?.let { checkedCount < it } ?: true
441-
if (enabled && canVote && !checked) {
442-
onCastVote.invoke()
443-
} else if (!enabled) {
444-
onRemoveVote.invoke()
445-
}
446-
},
465+
onCheckedChange = onToggle,
447466
borderColor = style.outlineColor,
448467
)
449468
}
@@ -468,8 +487,15 @@ private fun PollOptionItem(
468487
)
469488
}
470489

490+
val voteCountDescription = pluralStringResource(
491+
R.plurals.stream_compose_poll_vote_counts,
492+
voteCount,
493+
voteCount,
494+
)
471495
Text(
472-
modifier = Modifier.align(Alignment.CenterVertically),
496+
modifier = Modifier
497+
.align(Alignment.CenterVertically)
498+
.semantics { contentDescription = voteCountDescription },
473499
text = voteCount.toString(),
474500
style = typography.metadataDefault,
475501
color = style.textColor,
@@ -488,7 +514,8 @@ private fun PollOptionItem(
488514
modifier = Modifier
489515
.fillMaxWidth()
490516
.height(8.dp)
491-
.clip(RoundedCornerShape(4.dp)),
517+
.clip(RoundedCornerShape(4.dp))
518+
.clearAndSetSemantics {},
492519
progress = { progress },
493520
color = style.progressColor,
494521
trackColor = style.trackColor,

0 commit comments

Comments
 (0)