'Jetpack compose onClickLabel for Button and IconButton

Working on accessibility enhancements for my app.

From Docs, I can see that Card has both onClick and onClickLabel as part of the API.

And for composables without onClick, we can use Modifier.clickable or Modifier.semantics.

But what about Button, IconButton, FloatingActionButton, TextButton and OutlinedButton?
Composables which have onClick as part of API but no onClickLabel.

This works as expected. But is this the correct way to write this code?

IconButton(
    onClick = navigateUp,
    modifier = Modifier.clickable(
        onClickLabel = "Navigate up",
        onClick = {},
    )
) {
    Icon(
        imageVector = Icons.Rounded.ArrowBack,
        contentDescription = stringResource(
            id = R.string.top_app_bar_content_description_navigate_up,
        ),
    )
}

This seems too confusing as IconButton expects onClick. So I cannot go with completely Modifier.clickable or Modifier.semantics.
Similarly Modifier.clickable also expects onClick.

So, I have two onClick for a single composable component which could easily cause a lot of hard to debug bugs.

Reason for the change,
To read "Double tap to Navigate up" instead of the default "Double tap to activate".

P.S:
Compose version - 1.0.4



Solution 1:[1]

You don't need the Modifier.clickable in this scenario because:

  • the IconButton already handles clicks via its onClick lambda
  • the Icon has a contentDescription field for accessibility

So all you need is this

IconButton(
    onClick = navigateUp,
) {
    Icon(
        imageVector = Icons.Rounded.ArrowBack,
        contentDescription = stringResource(
            id = R.string.top_app_bar_content_description_navigate_up,
        ),
   )
}

Solution 2:[2]

It doesn't seem to be the prettiest solution but I ended up doing:

      IconButton(
        modifier = Modifier.size(40.dp).clearAndSetSemantics {
            this.onClick(label = closeLabelDescription, action = null)
            this.contentDescription = closeDescription
            this.role = Role.Button
        },
        onClick = onClickClose,
    ) {
        Icon(
            painter = painterResource(R.drawable.ic_close),
            tint = RiotWhite,
            contentDescription = null
        )
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Francesc
Solution 2 tiagocarvalho92