---
title: "ripple"
description: "Creates a Ripple using the provided values and values inferred from the theme."
type: "function"
---
## API Reference

### ripple

> Source set: Common

```kotlin
public fun ripple(
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified,
    color: Color = Color.Unspecified,
    focusRingShape: Shape? = null,
    enablePressIndication: Boolean = true,
    enableFocusIndication: Boolean = true,
    enableHoverIndication: Boolean = true,
    enableDragIndication: Boolean = true,
): IndicationNodeFactory
```

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of `Indication` that expresses different `Interaction`s by
drawing ripple animations and state layers.

A Ripple responds to `PressInteraction.Press` by starting a new ripple animation, and responds to
other `Interaction`s by showing a fixed state layer with varying alpha values depending on the
`Interaction`.

[MaterialTheme](/jetpack-compose/androidx.compose.material3/material3/objects/MaterialTheme/api) provides Ripples using `androidx.compose.foundation.LocalIndication`, so a Ripple
will be used as the default `Indication` inside components such as
`androidx.compose.foundation.clickable` and `androidx.compose.foundation.indication`, in addition
to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change
the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a manually defined color that can change over time, see the other
[ripple](/jetpack-compose/androidx.compose.material3/material3/functions/ripple/api) overload with a `ColorProducer` parameter. This will avoid unnecessary recompositions
when changing the color, and preserve existing ripple state when the color changes.

#### Parameters

| | |
| --- | --- |
| bounded | If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position. |
| radius | the radius for the ripple. If `Dp.Unspecified` is provided then the size will be calculated based on the target layout size. |
| color | the color of the ripple state layers. This color is usually the same color used by the text or iconography in the component. This color will then have an alpha applied to calculate the final color used to draw the ripple. If `Color.Unspecified` is provided the color used will be [LocalContentColor](/jetpack-compose/androidx.compose.material3/material3/properties/LocalContentColor) instead. If inset focus rings are enabled, their colors will be provided by the theme or by an overridden [LocalRippleConfiguration](/jetpack-compose/androidx.compose.material3/material3/properties/LocalRippleConfiguration). |
| focusRingShape | this parameter is only used if inset focus rings are enabled, specifically when the [RippleThemeConfiguration.focus](/jetpack-compose/androidx.compose.material3/material3/classes/RippleThemeConfiguration) from [LocalRippleThemeConfiguration](/jetpack-compose/androidx.compose.material3/material3/properties/LocalRippleThemeConfiguration) is [RippleThemeConfiguration.Focus.InsetRing](/jetpack-compose/androidx.compose.material3/material3/classes/RippleThemeConfiguration.Focus.InsetRing). When inset focus rings are enabled, the focus ring shape will define the shape of the ripple that the focus ring indication will use if specified. If left `null`, a default shape will be used, which will be a rounded rectangle based on the `radius` if specified, otherwise it will be just a [RectangleShape](/jetpack-compose/androidx.compose.ui/ui-graphics/properties/RectangleShape). This [Shape](/jetpack-compose/androidx.compose.ui/ui-graphics/interfaces/Shape) instance must remain the same during the lifetime of the ripple in composition. If the [Shape](/jetpack-compose/androidx.compose.ui/ui-graphics/interfaces/Shape) needs to change, delegate from a single instance to the changing shape to preserve the instance requirement. |
| enablePressIndication | if true, this ripple will draw the indication for press interactions. Set this to `false` to disable drawing any visuals for press interactions in this ripple. |
| enableFocusIndication | if true, this ripple will draw the indication for focus interactions. Set this to `false` to disable drawing any visuals for focus interactions in this ripple. |
| enableHoverIndication | if true, this ripple will draw the indication for hover interactions. Set this to `false` to disable drawing any visuals for hover interactions in this ripple. |
| enableDragIndication | if true, this ripple will draw the indication for drag interactions. Set this to `false` to disable drawing any visuals for drag interactions in this ripple. |

### ripple

> Source set: Common

```kotlin
@Deprecated("Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
public fun ripple(
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified,
    color: Color = Color.Unspecified,
): IndicationNodeFactory
```

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of `Indication` that expresses different `Interaction`s by
drawing ripple animations and state layers.

A Ripple responds to `PressInteraction.Press` by starting a new ripple animation, and responds to
other `Interaction`s by showing a fixed state layer with varying alpha values depending on the
`Interaction`.

[MaterialTheme](/jetpack-compose/androidx.compose.material3/material3/objects/MaterialTheme/api) provides Ripples using `androidx.compose.foundation.LocalIndication`, so a Ripple
will be used as the default `Indication` inside components such as
`androidx.compose.foundation.clickable` and `androidx.compose.foundation.indication`, in addition
to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change
the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a manually defined color that can change over time, see the other
[ripple](/jetpack-compose/androidx.compose.material3/material3/functions/ripple/api) overload with a `ColorProducer` parameter. This will avoid unnecessary recompositions
when changing the color, and preserve existing ripple state when the color changes.

#### Parameters

| | |
| --- | --- |
| bounded | If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position. |
| radius | the radius for the ripple. If `Dp.Unspecified` is provided then the size will be calculated based on the target layout size. |
| color | the color of the ripple. This color is usually the same color used by the text or iconography in the component. This color will then have [RippleDefaults.RippleAlpha](/jetpack-compose/androidx.compose.material/material-ripple/classes/RippleAlpha) applied to calculate the final color used to draw the ripple. If `Color.Unspecified` is provided the color used will be [LocalContentColor](/jetpack-compose/androidx.compose.material3/material3/properties/LocalContentColor) instead. |

### ripple

> Source set: Common

```kotlin
public fun ripple(
    color: ColorProducer,
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified,
    focusRingShape: Shape? = null,
    enablePressIndication: Boolean = true,
    enableFocusIndication: Boolean = true,
    enableHoverIndication: Boolean = true,
    enableDragIndication: Boolean = true,
): IndicationNodeFactory
```

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of `Indication` that expresses different `Interaction`s by
drawing ripple animations and state layers.

A Ripple responds to `PressInteraction.Press` by starting a new ripple animation, and responds to
other `Interaction`s by showing a fixed state layer with varying alpha values depending on the
`Interaction`.

[MaterialTheme](/jetpack-compose/androidx.compose.material3/material3/objects/MaterialTheme/api) provides Ripples using `androidx.compose.foundation.LocalIndication`, so a Ripple
will be used as the default `Indication` inside components such as
`androidx.compose.foundation.clickable` and `androidx.compose.foundation.indication`, in addition
to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change
the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a static color, see the [ripple](/jetpack-compose/androidx.compose.material3/material3/functions/ripple/api) overload with a `Color` parameter. This
overload is optimized for Ripples that have dynamic colors that change over time, to reduce
unnecessary recompositions.

#### Parameters

| | |
| --- | --- |
| color | the color of the ripple. This color is usually the same color used by the text or iconography in the component. This color will then have an alpha applied to calculate the final color used to draw the ripple. If you are creating this [ColorProducer](/jetpack-compose/androidx.compose.ui/ui-graphics/interfaces/ColorProducer) outside of composition (where it will be automatically remembered), make sure that its instance is stable (such as by remembering the object that holds it), or remember the returned [ripple](/jetpack-compose/androidx.compose.material3/material3/functions/ripple) object to make sure that ripple nodes are not being created each recomposition. If inset focus rings are enabled, their colors will be provided by the theme or by an overridden [LocalRippleConfiguration](/jetpack-compose/androidx.compose.material3/material3/properties/LocalRippleConfiguration). |
| bounded | If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position. |
| radius | the radius for the ripple. If `Dp.Unspecified` is provided then the size will be calculated based on the target layout size. |
| focusRingShape | this parameter is only used if inset focus rings are enabled, specifically when the [RippleThemeConfiguration.focus](/jetpack-compose/androidx.compose.material3/material3/classes/RippleThemeConfiguration) from [LocalRippleThemeConfiguration](/jetpack-compose/androidx.compose.material3/material3/properties/LocalRippleThemeConfiguration) is [RippleThemeConfiguration.Focus.InsetRing](/jetpack-compose/androidx.compose.material3/material3/classes/RippleThemeConfiguration.Focus.InsetRing). When inset focus rings are enabled, the focus ring shape will define the shape of the ripple that the focus ring indication will use if specified. If left `null`, a default shape will be used, which will be a rounded rectangle based on the `radius` if specified, otherwise it will be just a [RectangleShape](/jetpack-compose/androidx.compose.ui/ui-graphics/properties/RectangleShape). This [Shape](/jetpack-compose/androidx.compose.ui/ui-graphics/interfaces/Shape) instance must remain the same during the lifetime of the ripple in composition. If the [Shape](/jetpack-compose/androidx.compose.ui/ui-graphics/interfaces/Shape) needs to change, delegate from a single instance to the changing shape to preserve the instance requirement. |
| enablePressIndication | if true, this ripple will draw the indication for press interactions. Set this to `false` to disable drawing any visuals for press interactions in this ripple. |
| enableFocusIndication | if true, this ripple will draw the indication for focus interactions. Set this to `false` to disable drawing any visuals for focus interactions in this ripple. |
| enableHoverIndication | if true, this ripple will draw the indication for hover interactions. Set this to `false` to disable drawing any visuals for hover interactions in this ripple. |
| enableDragIndication | if true, this ripple will draw the indication for drag interactions. Set this to `false` to disable drawing any visuals for drag interactions in this ripple. |

### ripple

> Source set: Common

```kotlin
@Deprecated("Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
public fun ripple(
    color: ColorProducer,
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified,
): IndicationNodeFactory
```

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of `Indication` that expresses different `Interaction`s by
drawing ripple animations and state layers.

A Ripple responds to `PressInteraction.Press` by starting a new ripple animation, and responds to
other `Interaction`s by showing a fixed state layer with varying alpha values depending on the
`Interaction`.

[MaterialTheme](/jetpack-compose/androidx.compose.material3/material3/objects/MaterialTheme/api) provides Ripples using `androidx.compose.foundation.LocalIndication`, so a Ripple
will be used as the default `Indication` inside components such as
`androidx.compose.foundation.clickable` and `androidx.compose.foundation.indication`, in addition
to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change
the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a static color, see the [ripple](/jetpack-compose/androidx.compose.material3/material3/functions/ripple/api) overload with a `Color` parameter. This
overload is optimized for Ripples that have dynamic colors that change over time, to reduce
unnecessary recompositions.

#### Parameters

| | |
| --- | --- |
| color | the color of the ripple. This color is usually the same color used by the text or iconography in the component. This color will then have [RippleDefaults.RippleAlpha](/jetpack-compose/androidx.compose.material/material-ripple/classes/RippleAlpha) applied to calculate the final color used to draw the ripple. If you are creating this [ColorProducer](/jetpack-compose/androidx.compose.ui/ui-graphics/interfaces/ColorProducer) outside of composition (where it will be automatically remembered), make sure that its instance is stable (such as by remembering the object that holds it), or remember the returned [ripple](/jetpack-compose/androidx.compose.material3/material3/functions/ripple) object to make sure that ripple nodes are not being created each recomposition. |
| bounded | If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position. |
| radius | the radius for the ripple. If `Dp.Unspecified` is provided then the size will be calculated based on the target layout size. |

## Code Examples

### RippleSample

```kotlin
@Preview
@Sampled
@Composable
fun RippleSample() {
    val interactionSource = remember { MutableInteractionSource() }
    Box(
        modifier =
            Modifier.size(100.dp)
                .background(MaterialTheme.colorScheme.surfaceVariant)
                .clickable(
                    interactionSource = interactionSource,
                    indication = ripple(bounded = true, color = MaterialTheme.colorScheme.primary),
                    onClick = {},
                ),
        contentAlignment = Alignment.Center,
    ) {
        Text("Custom Ripple")
    }
}
```

### InsetFocusRingRippleSample

```kotlin
@Preview
@Sampled
@Composable
fun InsetFocusRingRippleSample() {
    // Enable inset focus rings at theme level
    CompositionLocalProvider(
        LocalRippleThemeConfiguration provides RippleDefaults.InsetFocusRingThemeConfiguration
    ) {
        // Components in this tree will render inset focus rings using theme colors when focused
        Button(onClick = {}) { Text("Button with Inset Focus Ring") }
    }
}
```

### RippleConfigurationInsetFocusRingSample

```kotlin
@Preview
@Sampled
@Composable
fun RippleConfigurationInsetFocusRingSample() {
    // Enable inset focus rings at theme level
    CompositionLocalProvider(
        LocalRippleThemeConfiguration provides RippleDefaults.InsetFocusRingThemeConfiguration
    ) {
        // Custom focus ring colors provided to a subtree via LocalRippleConfiguration
        val customFocusRingConfiguration =
            RippleConfiguration(
                focus =
                    RippleConfiguration.Focus.InsetRing(
                        outerStrokeColor = MaterialTheme.colorScheme.primary,
                        innerStrokeColor = MaterialTheme.colorScheme.onPrimary,
                    )
            )
        CompositionLocalProvider(LocalRippleConfiguration provides customFocusRingConfiguration) {
            val interactionSource = remember { MutableInteractionSource() }
            // Custom clickable element using inset focus ring with custom focusRingShape
            Box(
                modifier =
                    Modifier.size(120.dp)
                        .background(
                            MaterialTheme.colorScheme.surfaceVariant,
                            RoundedCornerShape(12.dp),
                        )
                        .clickable(
                            interactionSource = interactionSource,
                            indication = ripple(focusRingShape = RoundedCornerShape(12.dp)),
                            onClick = {},
                        ),
                contentAlignment = Alignment.Center,
            ) {
                Text("Custom Focus Ring")
            }
        }
    }
}
```

### DynamicColorRippleSample

```kotlin
@Preview
@Sampled
@Composable
fun DynamicColorRippleSample() {
    var isSelected by remember { mutableStateOf(false) }
    val primaryColor = MaterialTheme.colorScheme.primary
    val secondaryColor = MaterialTheme.colorScheme.secondary
    // ColorProducer reads state during draw, avoiding recomposition when the ripple color changes
    val colorProducer =
        remember(primaryColor, secondaryColor) {
            ColorProducer { if (isSelected) primaryColor else secondaryColor }
        }
    val interactionSource = remember { MutableInteractionSource() }

    Box(
        modifier =
            Modifier.size(100.dp)
                .background(MaterialTheme.colorScheme.surfaceVariant)
                .clickable(
                    interactionSource = interactionSource,
                    indication = ripple(color = colorProducer),
                    onClick = { isSelected = !isSelected },
                ),
        contentAlignment = Alignment.Center,
    ) {
        Text(if (isSelected) "Selected" else "Unselected")
    }
}
```
