TooltipBox

Composable Component

Material TooltipBox that wraps a composable with a tooltip.

Common

Deprecated Deprecated in favor of TooltipBox API that contains onDismissRequest and hasAction params.

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

Parameters

positionProviderPopupPositionProvider that will be used to place the tooltip relative to the anchor content.
tooltipthe composable that will be used to populate the tooltip's content.
statehandles the state of the tooltip's visibility.
modifierthe Modifier to be applied to the TooltipBox.
focusableBoolean 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.
enableUserInputBoolean which determines if this TooltipBox will handle long press and mouse hover to trigger the tooltip through the state provided.
contentthe composable that the tooltip will anchor to.
Common

Deprecated Deprecated in favor of TooltipBox API that contains hasAction param.

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

Parameters

positionProviderPopupPositionProvider that will be used to place the tooltip relative to the anchor content.
tooltipthe composable that will be used to populate the tooltip's content.
statehandles the state of the tooltip's visibility.
modifierthe Modifier to be applied to the TooltipBox.
onDismissRequestexecutes 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.
focusableBoolean 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.
enableUserInputBoolean which determines if this TooltipBox will handle long press and mouse hover to trigger the tooltip through the state provided.
contentthe composable that the tooltip will anchor to.
Common
@Composable
@ExperimentalMaterial3Api
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,
)

Parameters

positionProviderPopupPositionProvider that will be used to place the tooltip relative to the anchor content.
tooltipthe composable that will be used to populate the tooltip's content.
statehandles the state of the tooltip's visibility.
modifierthe Modifier to be applied to the TooltipBox.
onDismissRequestexecutes 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.
focusableBoolean 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.
enableUserInputBoolean which determines if this TooltipBox will handle long press and mouse hover to trigger the tooltip through the state provided.
hasActionwhether the associated tooltip contains an action.
contentthe composable that the tooltip will anchor to.

Code Examples

PlainTooltipSample

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun PlainTooltipSample() {
    TooltipBox(
        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
        tooltip = { PlainTooltip { Text("Add to favorites") } },
        state = rememberTooltipState(),
    ) {
        IconButton(onClick = { /* Icon button's click event */ }) {
            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
        }
    }
}

PlainTooltipWithManualInvocationSample

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun PlainTooltipWithManualInvocationSample() {
    val tooltipState = rememberTooltipState()
    val scope = rememberCoroutineScope()
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        TooltipBox(
            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
            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")
        }
    }
}

PlainTooltipWithCaret

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlainTooltipWithCaret() {
    TooltipBox(
        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
        tooltip = {
            PlainTooltip(caretSize = TooltipDefaults.caretSize) { Text("Add to favorites") }
        },
        state = rememberTooltipState(),
    ) {
        IconButton(onClick = { /* Icon button's click event */ }) {
            Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
        }
    }
}

PlainTooltipWithCustomCaret

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlainTooltipWithCustomCaret() {
    TooltipBox(
        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
        tooltip = { PlainTooltip(caretSize = 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")
        }
    }
}

RichTooltipSample

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RichTooltipSample() {
    val tooltipState = rememberTooltipState(isPersistent = true)
    val scope = rememberCoroutineScope()
    TooltipBox(
        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
        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")
        }
    }
}

RichTooltipWithManualInvocationSample

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RichTooltipWithManualInvocationSample() {
    val tooltipState = rememberTooltipState(isPersistent = true)
    val scope = rememberCoroutineScope()
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        TooltipBox(
            positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
            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")
        }
    }
}

RichTooltipWithCaretSample

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

RichTooltipWithCustomCaretSample

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RichTooltipWithCustomCaretSample() {
    val tooltipState = rememberTooltipState(isPersistent = true)
    val scope = rememberCoroutineScope()
    TooltipBox(
        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
        tooltip = {
            RichTooltip(
                title = { Text(richTooltipSubheadText) },
                action = {
                    TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                        Text(richTooltipActionText)
                    }
                },
                caretSize = 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")
        }
    }
}

Create your own Component Library

Material Components are meant to be used as is and they do not allow customizations. To build your own Jetpack Compose component library use Compose Unstyled