summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alejandro Nijamkin <nijamkin@google.com> 2025-03-05 19:50:24 -0800
committer Alejandro Nijamkin <nijamkin@google.com> 2025-03-06 08:08:00 -0800
commit9d97f851a28f0f06397f98d5447c0d9d826f66dc (patch)
tree496d368ed59e0500b4d4b8365e450190c7cfce39
parent626bcf1d28be476bb5a21a1574a73d7ba6ebf86d (diff)
[Media] Output device chip padding for a11y.
Adds top, bottom, and end padding to extend the touch target of the output device chip such that it's at least 48dp in height. This changes the top row to be a Box and the top-level padding around the entire card to be eliminated and replaced by padding around all three rows. Bug: 397989775 Test: manually verified in the compose gallery app that touching above, to the right, or right below the chip also triggers the chip and shows the ripple effect indication but only inside the chip bounds Flag: EXEMPT code isn't used yet Change-Id: I4dcc644e69be23df1a3641f9c69edea0011d24c6
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/remedia/ui/compose/Media.kt96
1 files changed, 64 insertions, 32 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/remedia/ui/compose/Media.kt b/packages/SystemUI/src/com/android/systemui/media/remedia/ui/compose/Media.kt
index 9c6568057d6f..9eb55a8eff2e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/remedia/ui/compose/Media.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/remedia/ui/compose/Media.kt
@@ -37,6 +37,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.hoverable
+import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.DragInteraction
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -44,7 +45,6 @@ import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
@@ -65,6 +65,7 @@ import androidx.compose.material3.SliderColors
import androidx.compose.material3.SliderDefaults.colors
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
+import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
@@ -376,29 +377,32 @@ private fun ContentScope.CardForegroundContent(
) {
Column(
modifier =
- modifier
- .combinedClickable(
- onClick = viewModel.onClick,
- onLongClick = viewModel.onLongClick,
- onClickLabel = viewModel.onClickLabel,
- )
- .padding(16.dp)
+ modifier.combinedClickable(
+ onClick = viewModel.onClick,
+ onLongClick = viewModel.onLongClick,
+ onClickLabel = viewModel.onClickLabel,
+ )
) {
// Always add the first/top row, regardless of presentation style.
- Row(verticalAlignment = Alignment.CenterVertically) {
+ Box(modifier = Modifier.fillMaxWidth()) {
// Icon.
Icon(
icon = viewModel.icon,
tint = colorScheme.primary,
- modifier = Modifier.size(24.dp).clip(CircleShape),
+ modifier =
+ Modifier.align(Alignment.TopStart)
+ .padding(top = 16.dp, start = 16.dp)
+ .size(24.dp)
+ .clip(CircleShape),
)
- Spacer(modifier = Modifier.weight(1f))
- viewModel.outputSwitcherChips.fastForEach { chip ->
- OutputSwitcherChip(
- viewModel = chip,
- colorScheme = colorScheme,
- modifier = Modifier.padding(start = 8.dp),
- )
+
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ modifier = Modifier.align(Alignment.TopEnd),
+ ) {
+ viewModel.outputSwitcherChips.fastForEach { chip ->
+ OutputSwitcherChip(viewModel = chip, colorScheme = colorScheme)
+ }
}
}
@@ -415,7 +419,7 @@ private fun ContentScope.CardForegroundContent(
// Second row.
Row(
verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.padding(top = 16.dp),
+ modifier = Modifier.padding(start = 16.dp, top = 16.dp, end = 16.dp),
) {
Metadata(
title = viewModel.title,
@@ -441,7 +445,7 @@ private fun ContentScope.CardForegroundContent(
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.padding(top = 24.dp),
+ modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp, bottom = 16.dp),
) {
Navigation(
viewModel = viewModel.navigation,
@@ -464,7 +468,7 @@ private fun ContentScope.CardForegroundContent(
// Bottom row.
Row(
verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.padding(top = 36.dp),
+ modifier = Modifier.padding(start = 16.dp, top = 36.dp, end = 16.dp, bottom = 16.dp),
) {
Metadata(
title = viewModel.title,
@@ -914,20 +918,48 @@ private fun OutputSwitcherChip(
colorScheme: AnimatedColorScheme,
modifier: Modifier = Modifier,
) {
- PlatformButton(
- onClick = viewModel.onClick,
- colors = ButtonDefaults.buttonColors(containerColor = colorScheme.primary),
- contentPadding = PaddingValues(start = 8.dp, end = 12.dp, top = 4.dp, bottom = 4.dp),
- modifier = modifier.height(24.dp),
+ // For accessibility reasons, the touch area for the chip needs to be at least 48dp in height.
+ // At the same time, the rounded corner chip should only be as tall as it needs to be to contain
+ // its contents and look like a nice design; also, the ripple effect should only be shown within
+ // the bounds of the chip.
+ //
+ // This is achieved by sharing this InteractionSource between the outer and inner composables.
+ //
+ // The outer composable hosts that clickable that writes user events into the InteractionSource.
+ // The inner composable consumes the user events from the InteractionSource and feeds them into
+ // its indication.
+ val clickInteractionSource = remember { MutableInteractionSource() }
+ Box(
+ modifier =
+ modifier
+ .height(48.dp)
+ .clickable(interactionSource = clickInteractionSource, indication = null) {
+ viewModel.onClick()
+ }
+ .padding(top = 16.dp, end = 16.dp, bottom = 8.dp)
) {
- Icon(icon = viewModel.icon, tint = colorScheme.onPrimary, modifier = Modifier.size(16.dp))
- viewModel.text?.let {
- Spacer(Modifier.size(4.dp))
- Text(
- text = viewModel.text,
- style = MaterialTheme.typography.bodySmall,
- color = colorScheme.onPrimary,
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ modifier =
+ Modifier.clip(RoundedCornerShape(12.dp))
+ .background(colorScheme.primary)
+ .indication(clickInteractionSource, ripple())
+ .padding(start = 8.dp, end = 12.dp, top = 4.dp, bottom = 4.dp),
+ ) {
+ Icon(
+ icon = viewModel.icon,
+ tint = colorScheme.onPrimary,
+ modifier = Modifier.size(16.dp),
)
+
+ viewModel.text?.let {
+ Text(
+ text = viewModel.text,
+ style = MaterialTheme.typography.bodySmall,
+ color = colorScheme.onPrimary,
+ )
+ }
}
}
}