mirror of
https://github.com/yuga-hashimoto/openclaw-assistant.git
synced 2026-08-14 08:47:12 +00:00
🎨 Palette: Improve accessibility of MissingScopeCard expand/collapse action (#395)
Added dynamic onClickLabel to MissingScopeCard to indicate whether clicking will Expand or Collapse the card content. Expandable cards using Jetpack Compose `Card(onClick=)` don't inform screen readers of their state change action, which creates a confusing experience for accessibility users. Visuals remain unchanged. Screen readers now announce "Expand" or "Collapse" dynamically instead of a generic button action. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
parent
e2b17c5c22
commit
e6a111a85c
@@ -13,3 +13,7 @@
|
||||
## 2025-02-13 - Redundant Screen Reader Announcements on Icons
|
||||
**Learning:** Adding a `contentDescription` to an `Icon` when the adjacent `Text` provides the exact same descriptive string causes screen readers (like TalkBack) to announce the action twice (e.g., "Scan QR Code, Scan QR Code").
|
||||
**Action:** When an `Icon` is used alongside descriptive text within a clickable area, set the `Icon`'s `contentDescription` to `null` so the screen reader only reads the text once.
|
||||
|
||||
## 2025-03-27 - Expand/Collapse Accessibility Pattern for MissingScopeCard
|
||||
**Learning:** Using `Card(onClick=)` without an `onClickLabel` leads to generic, unhelpful screen reader announcements. Expandable cards require explicit labels that change based on state (e.g. Expand / Collapse).
|
||||
**Action:** When converting `Card(onClick=)` to use `Modifier.clickable()`, use `onClickLabel = stringResource(if (expanded) R.string.action_collapse else R.string.action_expand)` and assign `role = Role.Button` so the action changes dynamically for screen readers.
|
||||
|
||||
@@ -49,6 +49,10 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.onClick
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.semantics.role
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -1265,8 +1269,15 @@ fun MissingScopeCard(error: String, onClick: () -> Unit) {
|
||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||
val context = LocalContext.current
|
||||
|
||||
val onClickLabel = stringResource(if (expanded) R.string.action_collapse else R.string.action_expand)
|
||||
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.semantics(mergeDescendants = true) {
|
||||
onClick(label = onClickLabel, action = null)
|
||||
role = Role.Button
|
||||
},
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.errorContainer),
|
||||
onClick = { expanded = !expanded }
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user