[a11y] Ensure that heading() is applied to all screen titles.

This commit is contained in:
Benoit Marty 2025-07-04 10:32:51 +02:00
parent f3eb0e69cc
commit 70aa31df00
42 changed files with 180 additions and 259 deletions

View file

@ -14,6 +14,8 @@ import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
@ -47,7 +49,10 @@ fun IconTitleSubtitleMolecule(
Text(
text = title,
modifier = Modifier
.fillMaxWidth(),
.fillMaxWidth()
.semantics {
heading()
},
textAlign = TextAlign.Center,
style = ElementTheme.typography.fontHeadingMdBold,
color = ElementTheme.colors.textPrimary,

View file

@ -21,6 +21,8 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
@ -78,6 +80,9 @@ private fun PreferenceTopAppBar(
},
title = {
Text(
modifier = Modifier.semantics {
heading()
},
text = title,
style = ElementTheme.typography.aliasScreenTitle,
maxLines = 1,

View file

@ -17,13 +17,66 @@ import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
/**
* A top app bar that displays a title string, navigation icon, and actions.
* @param titleStr The title string to display in the top app bar.
* @param modifier The [Modifier] to be applied to this top app bar.
* @param navigationIcon The content to display as the navigation icon.
* @param actions The content to display in the action area of the top app bar.
* @param windowInsets The window insets to apply to this top app bar.
* @param colors The colors used for this top app bar.
* @param scrollBehavior Optional scroll behavior for this top app bar.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TopAppBar(
titleStr: String,
modifier: Modifier = Modifier,
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = {
Text(
text = titleStr,
modifier = Modifier.semantics { heading() },
style = ElementTheme.typography.aliasScreenTitle,
)
},
modifier = modifier,
navigationIcon = navigationIcon,
actions = actions,
windowInsets = windowInsets,
colors = colors,
scrollBehavior = scrollBehavior,
)
}
/**
* A top app bar that displays a title, navigation icon, and actions.
*
* @param title The content to display as the title of the top app bar. Do not forget to apply `heading()` to
* the semantics of the title to ensure it is announced correctly by accessibility services.
* @param modifier The [Modifier] to be applied to this top app bar.
* @param navigationIcon The content to display as the navigation icon.
* @param actions The content to display in the action area of the top app bar.
* @param windowInsets The window insets to apply to this top app bar.
* @param colors The colors used for this top app bar.
* @param scrollBehavior Optional scroll behavior for this top app bar.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TopAppBar(
@ -68,3 +121,22 @@ internal fun TopAppBarPreview() = ElementThemedPreview {
}
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Preview(group = PreviewGroup.AppBars)
@Composable
internal fun TopAppBarStrPreview() = ElementThemedPreview {
TopAppBar(
titleStr = "Title string",
navigationIcon = { BackButton(onClick = {}) },
actions = {
TextButton(text = "Action", onClick = {})
IconButton(onClick = {}) {
Icon(
imageVector = CompoundIcons.ShareAndroid(),
contentDescription = null,
)
}
}
)
}