Added semantics to the invisible box

contentDescription - provides current state info
TODO: add translations
This commit is contained in:
David Kaspar
2025-08-22 09:49:25 +01:00
committed by davotoula
parent 0381e22198
commit f3f8beeebe
@@ -50,6 +50,12 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.onClick
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
@@ -59,13 +65,13 @@ import kotlinx.collections.immutable.ImmutableList
@Composable @Composable
fun TextSpinner( fun TextSpinner(
label: String?, modifier: Modifier = Modifier,
label: String? = null,
placeholder: String, placeholder: String,
options: ImmutableList<TitleExplainer>, options: ImmutableList<TitleExplainer>,
onSelect: (Int) -> Unit, onSelect: (Int) -> Unit,
modifier: Modifier = Modifier,
) { ) {
TextSpinner( BaseTextSpinner(
placeholder, placeholder,
options, options,
onSelect, onSelect,
@@ -89,12 +95,36 @@ fun TextSpinner(
onSelect: (Int) -> Unit, onSelect: (Int) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
mainElement: @Composable (currentOption: String, modifier: Modifier) -> Unit, mainElement: @Composable (currentOption: String, modifier: Modifier) -> Unit,
) {
BaseTextSpinner(
placeholder = placeholder,
options = options,
onSelect = onSelect,
modifier = modifier,
mainElement = mainElement,
)
}
@Composable
private fun BaseTextSpinner(
placeholder: String,
options: ImmutableList<TitleExplainer>,
onSelect: (Int) -> Unit,
modifier: Modifier = Modifier,
mainElement: @Composable (currentOption: String, modifier: Modifier) -> Unit,
) { ) {
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
var optionsShowing by remember { mutableStateOf(false) } var optionsShowing by remember { mutableStateOf(false) }
var currentText by remember(placeholder) { mutableStateOf(placeholder) } var currentText by remember(placeholder) { mutableStateOf(placeholder) }
val accessibilityDescription =
if (currentText == placeholder) {
"Dropdown menu, $placeholder, not selected"
} else {
"Dropdown menu, $currentText selected"
}
Box( Box(
modifier = modifier, modifier = modifier,
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
@@ -105,13 +135,23 @@ fun TextSpinner(
) )
Box( Box(
modifier = modifier =
Modifier.matchParentSize().clickable( Modifier
interactionSource = interactionSource, .matchParentSize()
indication = null, .clickable(
) { interactionSource = interactionSource,
optionsShowing = true indication = null,
focusRequester.requestFocus() ) {
}, optionsShowing = true
focusRequester.requestFocus()
}.semantics {
role = Role.DropdownList
stateDescription = accessibilityDescription
onClick(label = "Open dropdown menu") {
optionsShowing = true
focusRequester.requestFocus()
return@onClick true
}
},
) )
} }
@@ -188,7 +228,15 @@ fun <T> SpinnerSelectionDialog(
} }
itemsIndexed(options) { index, item -> itemsIndexed(options) { index, item ->
Row( Row(
modifier = Modifier.fillMaxWidth().clickable { onSelect(index) }.padding(16.dp, 16.dp), modifier =
Modifier
.fillMaxWidth()
.clickable { onSelect(index) }
.padding(16.dp, 16.dp)
.semantics {
role = Role.Button
contentDescription = "Option ${index + 1} of ${options.size}"
},
) { ) {
Column { onRenderItem(item) } Column { onRenderItem(item) }
} }