Build apps faster with our new App builder! Check it out →

minimumInteractiveComponentSize

Common

Modifier in Material 3 Compose

Reserves at least 48.dp in size to disambiguate touch interactions if the element would measure smaller.

https://m3.material.io/foundations/designing/structure#dab862b1-e042-4c40-b680-b484b9f077f6

This uses the Material recommended minimum size of 48.dp x 48.dp, which may not the same as the system enforced minimum size. The minimum clickable / touch target size (48.dp by default) is controlled by the system via [ViewConfiguration] and automatically expanded at the touch input layer.

This modifier is not needed for touch target expansion to happen. It only affects layout, to make sure there is adequate space for touch target expansion.

Because layout constraints are affected by modifier order, for this modifier to take effect, it must come before any size modifiers on the element that might limit its constraints.

@sample androidx.compose.material3.samples.MinimumInteractiveComponentSizeSample @sample androidx.compose.material3.samples.MinimumInteractiveComponentSizeCheckboxRowSample @see LocalMinimumInteractiveComponentSize

Last updated:

Installation

dependencies {
   implementation("androidx.compose.material3:material3:1.4.0-alpha02")
}

Overloads

@Stable
fun Modifier.minimumInteractiveComponentSize(): Modifier

Code Examples

MinimumInteractiveComponentSizeSample

@Preview
@Composable
fun MinimumInteractiveComponentSizeSample() {
    @Composable
    fun Widget(color: Color, modifier: Modifier = Modifier) {
        // Default size is 24.dp, which is smaller than the recommended touch target
        Box(modifier.size(24.dp).background(color))
    }

    Column(Modifier.border(1.dp, Color.Black)) {
        // Not interactable, no need for touch target enforcement
        Widget(Color.Red)

        Widget(
            color = Color.Green,
            modifier =
                Modifier.clickable { /* do something */ }
                    // Component is now interactable, so it should enforce a sufficient touch target
                    .minimumInteractiveComponentSize()
        )

        Widget(
            color = Color.Blue,
            modifier =
                Modifier.clickable { /* do something */ }
                    // Component is now interactable, so it should enforce a sufficient touch target
                    .minimumInteractiveComponentSize()
                    // Any size modifiers should come after `minimumInteractiveComponentSize`
                    // so as not to interfere with layout expansion
                    .size(36.dp)
        )
    }
}

MinimumInteractiveComponentSizeCheckboxRowSample

@Preview
@Composable
fun MinimumInteractiveComponentSizeCheckboxRowSample() {
    var checked by remember { mutableStateOf(false) }

    // The entire row accepts interactions to toggle the checkbox,
    // so we apply `minimumInteractiveComponentSize`
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier =
            Modifier.toggleable(
                    value = checked,
                    onValueChange = { checked = it },
                    role = Role.Checkbox,
                )
                .minimumInteractiveComponentSize()
    ) {
        // Cannot rely on Checkbox for touch target expansion because it only enforces
        // `minimumInteractiveComponentSize` if onCheckedChange is non-null
        Checkbox(checked = checked, onCheckedChange = null)
        Spacer(Modifier.width(8.dp))
        Text("Label for checkbox")
    }
}
by @alexstyl