From f5b5bb39baeff35a3934eb45074eed6c4b3c27c7 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 1 Sep 2025 15:27:40 +0200 Subject: [PATCH] [a11y] Add click action to the message bottom sheet handle (#5228) --- .../features/messages/impl/MessagesView.kt | 24 ++++++++++++++++++- .../components/ExpandableBottomSheetLayout.kt | 16 +++++++++++-- .../ExpandableBottomSheetLayoutState.kt | 2 +- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index ccbebbbc6d..6a436adabc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -39,7 +39,10 @@ import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextAlign @@ -81,6 +84,7 @@ import io.element.android.features.roomcall.api.RoomCallState import io.element.android.libraries.androidutils.ui.hideKeyboard import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule import io.element.android.libraries.designsystem.components.ExpandableBottomSheetLayout +import io.element.android.libraries.designsystem.components.ExpandableBottomSheetLayoutState import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarType @@ -288,7 +292,25 @@ fun MessagesView( ) }, sheetDragHandle = if (state.composerState.showTextFormatting) { - @Composable { BottomSheetDragHandle() } + @Composable { toggleAction -> + val expandA11yLabel = stringResource(CommonStrings.a11y_expand_message_text_field) + val collapseA11yLabel = stringResource(CommonStrings.a11y_collapse_message_text_field) + BottomSheetDragHandle( + modifier = Modifier.semantics { + role = Role.Button + + // Accessibility action to toggle the bottom sheet state + val label = when (expandableState.position) { + ExpandableBottomSheetLayoutState.Position.COLLAPSED, ExpandableBottomSheetLayoutState.Position.DRAGGING -> expandA11yLabel + ExpandableBottomSheetLayoutState.Position.EXPANDED -> collapseA11yLabel + } + onClick(label) { + toggleAction() + true + } + } + ) + } } else { @Composable {} }, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt index 66b404f554..1caf5c50b7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt @@ -60,7 +60,7 @@ import kotlin.math.roundToInt @Composable fun ExpandableBottomSheetLayout( - sheetDragHandle: @Composable BoxScope.() -> Unit, + sheetDragHandle: @Composable BoxScope.(toggleAction: () -> Unit) -> Unit, bottomSheetContent: @Composable ColumnScope.() -> Unit, state: ExpandableBottomSheetLayoutState, maxBottomSheetContentHeight: Dp, @@ -152,7 +152,19 @@ fun ExpandableBottomSheetLayout( } ) { Box(Modifier.fillMaxWidth()) { - sheetDragHandle() + sheetDragHandle { + coroutineScope.launch { + val destination = if (state.position == ExpandableBottomSheetLayoutState.Position.EXPANDED) { + state.internalPosition = ExpandableBottomSheetLayoutState.Position.COLLAPSED + minBottomContentHeightPx.toFloat() + } else { + state.internalPosition = ExpandableBottomSheetLayoutState.Position.EXPANDED + calculatedMaxBottomContentHeightPx.toFloat() + } + animatable.snapTo(currentBottomContentHeightPx.toFloat()) + animatable.animateTo(destination) + } + } } bottomSheetContent() } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayoutState.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayoutState.kt index eda4cd73b2..71fb2d06be 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayoutState.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayoutState.kt @@ -38,7 +38,7 @@ class ExpandableBottomSheetLayoutState { /** * The current position of the bottom sheet layout. */ - val position = internalPosition + val position get() = internalPosition /** * The percentage of the bottom sheet layout that is currently being dragged.