TooltipBox

Functions summary

Unit
@Composable
TooltipBox(
    positionProvider: PopupPositionProvider,
    tooltip: @Composable TooltipScope.() -> Unit,
    state: TooltipState,
    modifier: Modifier,
    onDismissRequest: (() -> Unit)?,
    focusable: Boolean,
    enableUserInput: Boolean,
    hasAction: Boolean,
    content: @Composable () -> Unit
)

Material TooltipBox that wraps a composable with a tooltip.

Cmn

Functions

TooltipBox

@Composable
fun TooltipBox(
    positionProvider: PopupPositionProvider,
    tooltip: @Composable TooltipScope.() -> Unit,
    state: TooltipState,
    modifier: Modifier = Modifier,
    onDismissRequest: (() -> Unit)? = null,
    focusable: Boolean = false,
    enableUserInput: Boolean = true,
    hasAction: Boolean = false,
    content: @Composable () -> Unit
): Unit

Material TooltipBox that wraps a composable with a tooltip.

Tooltips provide a descriptive message for an anchor. It can be used to call the users attention to the anchor.

Tooltip that is invoked when the anchor is long pressed:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
    tooltip = { PlainTooltip { Text("Add to favorites") } },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

If control of when the tooltip is shown is desired please see

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val tooltipState = rememberTooltipState()
val scope = rememberCoroutineScope()
Column(horizontalAlignment = Alignment.CenterHorizontally) {
    TooltipBox(
        positionProvider =
            TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
        tooltip = { PlainTooltip { Text("Add to list") } },
        state = tooltipState,
    ) {
        IconButton(onClick = { /* Icon button's click event */ }) {
            Icon(
                imageVector = Icons.Filled.AddCircle,
                contentDescription = "Localized Description",
            )
        }
    }
    Spacer(Modifier.requiredHeight(30.dp))
    OutlinedButton(onClick = { scope.launch { tooltipState.show() } }) {
        Text("Display tooltip")
    }
}

Plain tooltip with caret shown on long press:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
    tooltip = {
        PlainTooltip(caretShape = TooltipDefaults.caretShape()) { Text("Add to favorites") }
    },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Plain tooltip with caret shown on long press which is placed below the anchor:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Below),
    tooltip = {
        PlainTooltip(caretShape = TooltipDefaults.caretShape()) { Text("Add to favorites") }
    },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Plain tooltip with caret shown on long press which is placed left of the anchor:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Left),
    tooltip = {
        PlainTooltip(caretShape = TooltipDefaults.caretShape()) { Text("Add to favorites") }
    },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Plain tooltip with caret shown on long press which is placed right of the anchor:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Right),
    tooltip = {
        PlainTooltip(caretShape = TooltipDefaults.caretShape()) { Text("Add to favorites") }
    },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Plain tooltip with caret shown on long press which is placed start of the anchor:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Start),
    tooltip = {
        PlainTooltip(caretShape = TooltipDefaults.caretShape()) { Text("Add to favorites") }
    },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Plain tooltip with caret shown on long press which is placed end of the anchor:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.End),
    tooltip = {
        PlainTooltip(caretShape = TooltipDefaults.caretShape()) { Text("Add to favorites") }
    },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Plain tooltip shown on long press with a custom caret:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
    tooltip = {
        PlainTooltip(caretShape = TooltipDefaults.caretShape(DpSize(24.dp, 12.dp))) {
            Text("Add to favorites")
        }
    },
    state = rememberTooltipState(),
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Tooltip that is invoked when the anchor is long pressed:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
    tooltip = {
        RichTooltip(
            title = { Text(richTooltipSubheadText) },
            action = {
                TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                    Text(richTooltipActionText)
                }
            },
        ) {
            Text(richTooltipText)
        }
    },
    hasAction = true,
    state = tooltipState,
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
    }
}

If control of when the tooltip is shown is desired please see

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
Column(horizontalAlignment = Alignment.CenterHorizontally) {
    TooltipBox(
        positionProvider =
            TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
        tooltip = {
            RichTooltip(
                title = { Text(richTooltipSubheadText) },
                action = {
                    TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                        Text(richTooltipActionText)
                    }
                },
            ) {
                Text(richTooltipText)
            }
        },
        hasAction = true,
        state = tooltipState,
    ) {
        IconButton(onClick = { /* Icon button's click event */ }) {
            Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
        }
    }
    Spacer(Modifier.requiredHeight(30.dp))
    OutlinedButton(onClick = { scope.launch { tooltipState.show() } }) {
        Text("Display tooltip")
    }
}

Rich tooltip with caret shown on long press:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
    tooltip = {
        RichTooltip(
            title = { Text(richTooltipSubheadText) },
            action = {
                TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                    Text(richTooltipActionText)
                }
            },
            caretShape = TooltipDefaults.caretShape(),
        ) {
            Text(richTooltipText)
        }
    },
    hasAction = true,
    state = tooltipState,
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
    }
}

Rich tooltip shown on long press with a custom caret

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
TooltipBox(
    positionProvider =
        TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
    tooltip = {
        RichTooltip(
            title = { Text(richTooltipSubheadText) },
            action = {
                TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                    Text(richTooltipActionText)
                }
            },
            caretShape = TooltipDefaults.caretShape(DpSize(32.dp, 16.dp)),
        ) {
            Text(richTooltipText)
        }
    },
    hasAction = true,
    state = tooltipState,
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
    }
}
Parameters
positionProvider: PopupPositionProvider

PopupPositionProvider that will be used to place the tooltip relative to the anchor content.

tooltip: @Composable TooltipScope.() -> Unit

the composable that will be used to populate the tooltip's content.

state: TooltipState

handles the state of the tooltip's visibility.

modifier: Modifier = Modifier

the Modifier to be applied to the TooltipBox.

onDismissRequest: (() -> Unit)? = null

executes when the user clicks outside of the tooltip. By default, the tooltip will dismiss when it's being shown when a user clicks outside of the tooltip.

focusable: Boolean = false

Boolean that determines if the tooltip is focusable. When true, the tooltip will consume touch events while it's shown and will have accessibility focus move to the first element of the component. When false, the tooltip won't consume touch events while it's shown but assistive-tech users will need to swipe or drag to get to the first element of the component. For certain a11y cases, such as when the tooltip has an action and Talkback is on, focusable will be forced to true to allow for the correct a11y behavior.

enableUserInput: Boolean = true

Boolean which determines if this TooltipBox will handle long press and, mouse hover, and keyboard focus to trigger the tooltip through the state provided.

hasAction: Boolean = false

whether the associated tooltip contains an action.

content: @Composable () -> Unit

the composable that the tooltip will anchor to.