From 620f1865e8db8fc46a005aa1fb822d7e7fb6ab7f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:39:11 +0200 Subject: [PATCH 1/4] [a11y] Improve accessibility of screen headers. --- .../impl/threads/list/ThreadsListView.kt | 16 ++++++++++++- .../impl/topbars/MessagesViewTopBar.kt | 8 +++---- .../messages/impl/topbars/ThreadTopBar.kt | 23 +++++++++++++------ .../src/main/res/values/localazy.xml | 2 ++ 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt index 1beabcd3fa..5e26d849a5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt @@ -31,6 +31,9 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.heading import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -79,7 +82,18 @@ fun ThreadsListView( topBar = { TopAppBar( title = { - Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) { + val description = stringResource( + CommonStrings.a11y_threads_in_room, + state.roomName, + ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clearAndSetSemantics { + heading() + contentDescription = description + }, + ) { Avatar( avatarData = AvatarData( id = state.roomId.value, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index 639092fc6c..4f023ad2bd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -80,7 +80,8 @@ internal fun MessagesViewTopBar( Row( modifier = Modifier .clip(roundedCornerShape) - .clickable { onRoomDetailsClick() }, + .clickable { onRoomDetailsClick() } + .semantics { heading() }, horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.CenterVertically, ) { @@ -158,10 +159,7 @@ private fun RoomAvatarAndNameRow( ) Text( modifier = Modifier - .padding(start = 8.dp) - .semantics { - heading() - }, + .padding(start = 8.dp), text = roomName ?: stringResource(CommonStrings.common_no_room_name), style = ElementTheme.typography.fontBodyLgMedium, fontStyle = FontStyle.Italic.takeIf { roomName == null }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt index e73b6b19b7..5ef4541f06 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt @@ -17,8 +17,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.heading -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -58,7 +59,18 @@ internal fun ThreadTopBar( BackButton(onClick = onBackClick) }, title = { - Row(verticalAlignment = Alignment.CenterVertically) { + val name = roomName ?: stringResource(CommonStrings.common_no_room_name) + val description = stringResource( + CommonStrings.a11y_thread_in_room, + name, + ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clearAndSetSemantics { + heading() + contentDescription = description + }, + ) { Avatar( avatarData = roomAvatarData, avatarType = AvatarType.Room( @@ -69,17 +81,14 @@ internal fun ThreadTopBar( Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 8.dp) - .semantics { - heading() - }, + .padding(horizontal = 8.dp), ) { Text( text = stringResource(CommonStrings.common_thread), style = ElementTheme.typography.fontBodyLgMedium, ) Text( - text = roomName ?: stringResource(CommonStrings.common_no_room_name), + text = name, style = ElementTheme.typography.fontBodySmRegular, fontStyle = FontStyle.Italic.takeIf { roomName == null }, color = ElementTheme.colors.textSecondary, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index ee0f51000a..6fa5436f96 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -54,6 +54,8 @@ "Start a call" "Start a video call" "Start a voice call" + "Thread in %1$s" + "Threads in %1$s" "Tombstoned room" "User avatar" "User menu" From 5b2970f78906cb22312dcbcc0c37036c114804a8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:49:18 +0200 Subject: [PATCH 2/4] [a11y] Improve accessibility of screen headers. --- .../mediaviewer/impl/viewer/MediaViewerView.kt | 14 +++++++++++--- .../ui-strings/src/main/res/values/localazy.xml | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index d52db124ea..3a7c006593 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -55,6 +55,8 @@ import androidx.compose.ui.layout.onVisibilityChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextOverflow @@ -495,14 +497,20 @@ private fun MediaViewerTopBar( TopAppBar( title = { if (senderName != null && dateSent != null) { + val description = stringResource( + CommonStrings.a11y_sent_by_sender_at_date, + senderName, + dateSent, + ) Column( modifier = Modifier .fillMaxWidth() + .clearAndSetSemantics { + heading() + contentDescription = description + }, ) { Text( - modifier = Modifier.semantics { - heading() - }, text = senderName, style = ElementTheme.typography.fontBodyMdMedium, color = ElementTheme.colors.textPrimary, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 6fa5436f96..1c94927623 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -48,6 +48,7 @@ "Room avatar" "Send files" "Sender location" + "Sent by %1$s at %2$s" "Time limited action required, you have one minute to verify" "Settings, action required" "Show password" From c2e357cbcdc4aa519cbc38690da7c860cafeaf94 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:52:46 +0200 Subject: [PATCH 3/4] [a11y] Improve accessibility of screen headers. --- .../android/features/space/impl/root/SpaceView.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt index 05fb75ee5e..29898a1f63 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt @@ -354,7 +354,8 @@ private fun EmptySpaceView( title = stringResource(R.string.screen_space_empty_state_title), subTitle = null, iconStyle = BigIcon.Style.Default(vectorIcon = CompoundIcons.Room(), usePrimaryTint = true), - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(top = 40.dp, start = 24.dp, end = 24.dp, bottom = 24.dp), ) ButtonColumnMolecule( @@ -425,6 +426,7 @@ private fun SpaceViewTopBar( modifier = Modifier .clip(roundedCornerShape) .clickable(enabled = canAccessSpaceSettings, onClick = onSettingsClick) + .semantics { heading() } ) }, actions = { @@ -532,6 +534,7 @@ private fun ManageModeTopBar( Text( text = pluralStringResource(CommonPlurals.common_selected_count, selectedCount, selectedCount), style = ElementTheme.typography.fontBodyLgMedium, + modifier = Modifier.semantics { heading() }, ) }, actions = { @@ -585,10 +588,7 @@ private fun SpaceAvatarAndNameRow( ) Text( modifier = Modifier - .padding(horizontal = 8.dp) - .semantics { - heading() - }, + .padding(horizontal = 8.dp), text = name ?: stringResource(CommonStrings.common_no_space_name), style = ElementTheme.typography.fontBodyLgMedium, fontStyle = FontStyle.Italic.takeIf { name == null }, From df9a3fe9c2b2aee793618b92c4f24fc43fb59af9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:53:08 +0200 Subject: [PATCH 4/4] [a11y] Improve accessibility of screen headers. --- .../element/android/features/joinroom/impl/JoinRoomView.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 35cfbb1594..977308178d 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -609,6 +609,7 @@ private fun JoinRoomTopBar( val roundedCornerShape = RoundedCornerShape(8.dp) val titleModifier = Modifier .clip(roundedCornerShape) + .semantics { heading() } if (contentState.name != null) { Row( modifier = titleModifier, @@ -621,10 +622,7 @@ private fun JoinRoomTopBar( ) Text( modifier = Modifier - .padding(horizontal = 8.dp) - .semantics { - heading() - }, + .padding(horizontal = 8.dp), text = contentState.name, style = ElementTheme.typography.fontBodyLgMedium, maxLines = 1,