mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 16:10:00 +00:00
Merge pull request #7885 from element-hq/feature/bma/selectedItemFocus
Draw the keyboard focus indicator around the whole selected item
This commit is contained in:
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2026 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.designsystem.utils
|
||||||
|
|
||||||
|
import androidx.compose.ui.input.key.Key
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keys which can be used to activate (i.e. click) the component having the keyboard focus.
|
||||||
|
*/
|
||||||
|
val activationKeys = setOf(
|
||||||
|
Key.Enter,
|
||||||
|
Key.NumPadEnter,
|
||||||
|
Key.DirectionCenter,
|
||||||
|
Key.Spacebar,
|
||||||
|
)
|
||||||
+32
@@ -9,6 +9,8 @@
|
|||||||
package io.element.android.libraries.matrix.ui.components
|
package io.element.android.libraries.matrix.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.focusable
|
||||||
|
import androidx.compose.foundation.indication
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -25,11 +27,16 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.clipToBounds
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.draw.drawWithContent
|
import androidx.compose.ui.draw.drawWithContent
|
||||||
|
import androidx.compose.ui.focus.focusProperties
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.BlendMode
|
import androidx.compose.ui.graphics.BlendMode
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.CompositingStrategy
|
import androidx.compose.ui.graphics.CompositingStrategy
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
|
import androidx.compose.ui.input.key.KeyEventType
|
||||||
|
import androidx.compose.ui.input.key.key
|
||||||
|
import androidx.compose.ui.input.key.onKeyEvent
|
||||||
|
import androidx.compose.ui.input.key.type
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||||
@@ -48,6 +55,7 @@ import io.element.android.libraries.designsystem.text.toPx
|
|||||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
|
import io.element.android.libraries.designsystem.utils.activationKeys
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -62,9 +70,31 @@ fun SelectedItem(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val actionRemove = stringResource(id = CommonStrings.action_remove)
|
val actionRemove = stringResource(id = CommonStrings.action_remove)
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.width(avatarData.size.dp)
|
.width(avatarData.size.dp)
|
||||||
|
.then(
|
||||||
|
if (canRemove) {
|
||||||
|
// Let the whole item get the keyboard focus, so that the focus indicator is drawn around it.
|
||||||
|
Modifier
|
||||||
|
.onKeyEvent { event ->
|
||||||
|
if (event.type == KeyEventType.KeyUp && event.key in activationKeys) {
|
||||||
|
onRemoveClick()
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.indication(
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
indication = ripple(),
|
||||||
|
)
|
||||||
|
.focusable(interactionSource = interactionSource)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
)
|
||||||
.clearAndSetSemantics {
|
.clearAndSetSemantics {
|
||||||
contentDescription = a11yContentDescription
|
contentDescription = a11yContentDescription
|
||||||
if (canRemove) {
|
if (canRemove) {
|
||||||
@@ -130,6 +160,8 @@ fun SelectedItem(
|
|||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.size(20.dp)
|
.size(20.dp)
|
||||||
.align(Alignment.TopEnd)
|
.align(Alignment.TopEnd)
|
||||||
|
// The whole item is focusable, not the remove button
|
||||||
|
.focusProperties { canFocus = false }
|
||||||
.clickable(
|
.clickable(
|
||||||
indication = ripple(),
|
indication = ripple(),
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
|
|||||||
Reference in New Issue
Block a user