@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }

Basic Example

The Tooltip component has 2 main slots: its panel and its anchor.

The anchor contains the element to which the tooltip is anchored. When this element has focus, is hovered or long-pressed (on touch) the tooltip will be displayed.

The panel contains one of the overloads of TooltipPanel which renders the content of the tooltip according to the Tooltip's internal state.

Tooltips are placed in the same layout as the trigger. This is different to how Tooltips work in Compose Foundation, in order to prevent any focus and pointer issues. Because of this, you need to use Modifier.zIndex() to your panel to place it above other elements in the same layout.

Tooltip(
    placement = RelativeAlignment.TopCenter,
    panel = {
        TooltipPanel(
            modifier = Modifier.zIndex(15f),
            enter = slideInVertically(tween(150), initialOffsetY = { (it * 0.25).toInt() }) +
                    scaleIn(
                        animationSpec = tween(150),
                        transformOrigin = TransformOrigin(0.5f, 1f),
                        initialScale = 0.65f
                    ) + fadeIn(tween(150)),
            exit = fadeOut(tween(250)),
            arrow = { direction ->
                val degrees = when (direction) {
                    TooltipArrowDirection.Up -> 0f
                    TooltipArrowDirection.Down -> 180f
                    TooltipArrowDirection.Left -> 90f
                    TooltipArrowDirection.Right -> 270f
                }
                ArrowUp(Modifier.rotate(degrees), Color.Black.copy(0.8f))
            }
        ) {
            Box(
                modifier = Modifier
                    .clip(RoundedCornerShape(100))
                    .background(Color.Black.copy(0.8f))
                    .padding(vertical = 8.dp, horizontal = 12.dp),
            ) {
                Text("Notifications", color = Color.White)
            }
        }
    }
) {
    val interactionSource = remember { MutableInteractionSource() }

    Button(
        onClick = { },
        contentPadding = PaddingValues(8.dp),
        shape = CircleShape,
        modifier = Modifier.focusRing(interactionSource, 1.dp, Color(0xFF3B82F6), CircleShape),
        interactionSource = interactionSource
    ) {
        Icon(Lucide.BellDot, contentDescription = null)
    }
}

Code Examples

Styling the Tooltip

The TooltipPanel composable contains styling properties such as backgroundColor, contentColor, shape and contentPadding for easy styling.

Tooltip(
    placement = RelativeAlignment.TopCenter,
    panel = {
        TooltipPanel(
            modifier = Modifier.zIndex(15f),
            backgroundColor = Color(0xFF1E293B),
            contentColor = Color.White,
            shape = RoundedCornerShape(8.dp),
            contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp)
        ) {
            Text("Styled tooltip")
        }
    }
) {
    Button(onClick = {}) {
        Text("Hover me")
    }
}

Positioning the Tooltip

Pass the relative alignment you want to the Tooltip's placement property:

Tooltip(
    placement = RelativeAlignment.TopEnd,
    panel = {
        TooltipPanel {
            Text("This is a tooltip")
        }
    }
) {
    Button(onClick = {}) {
        Text("Hover me")
    }
}

Tooltip with Arrow (Caret)

Use the TooltipPanel with the arrow parameter. The arrow lambda gives you the TooltipArrowDirection which the arrow needs to be pointing towards.

We will always place the arrow between the anchor and the panel centering it to the respective direction.

@Composable
fun ArrowUp(modifier: Modifier = Modifier, color: Color) {
    Canvas(modifier = modifier.size(8.dp, 4.dp)) {
        val path = Path().apply {
            moveTo(size.width / 2f, 0f)
            lineTo(0f, size.height)
            lineTo(size.width, size.height)
            close()
        }
        drawPath(path, color = color)
    }
}

Tooltip(
    placement = RelativeAlignment.BottomCenter,
    panel = {
        TooltipPanel(
            modifier = Modifier.zIndex(15f),
            arrow = { direction ->
                // Draw your arrow pointing towards the given direction
                val degrees = when (direction) {
                    TooltipArrowDirection.Up -> 0f
                    TooltipArrowDirection.Down -> 180f
                    TooltipArrowDirection.Left -> 90f
                    TooltipArrowDirection.Right -> 270f
                }
                ArrowUp(Modifier.rotate(degrees), Color.Black)
            }
        ) {
            Text("Tooltip with arrow")
        }
    }
) {
    Button(onClick = {}) {
        Text("Hover me")
    }
}

Animating the Tooltip

Pass the respective animation specs you want in the TooltipPanel's enter and exit parameters:

Tooltip(
    placement = RelativeAlignment.TopCenter,
    panel = {
        TooltipPanel(
            modifier = Modifier.zIndex(15f),
            enter = fadeIn(animationSpec = tween(300)),
            exit = fadeOut(animationSpec = tween(300))
        ) {
            Text("This tooltip fades in and out")
        }
    }
) {
    Button(onClick = {}) {
        Text("Hover me")
    }
}

Unstyled Tooltip vs Compose Foundation Tooltips

Tooltips in Compose Foundation are implemented using Popups. Popups do not allow pointer events behind them. This can cause weird glitches when the Tooltip is right above the trigger and mouse overed.

Unstyled Tooltips are placed in the same layout as its trigger, and do not use Popups. As a result, there are no weird focus or pointer issues.

Keyboard Interactions

KeyDescription
Escape
Dismisses the tooltip when it is visible.

Component API

Tooltip

ParameterDescription
enabledWhether the tooltip is enabled. When disabled, the tooltip will not show.
panelA composable function that defines the tooltip content panel.
placementThe relative alignment of the tooltip to the anchor element. Default is TopCenter.
longPressShowDurationMillisDuration in milliseconds to show the tooltip after a long press. Default is 1500ms.
hoverDelayMillisDelay in milliseconds before showing the tooltip on hover. Default is 0ms.
anchorA composable function that defines the anchor element that triggers the tooltip.

TooltipPanel

ParameterDescription
modifierModifier to be applied to the tooltip panel.
enterThe enter transition for the tooltip panel. Default is instant appearance.
exitThe exit transition for the tooltip panel. Default is instant disappearance.
shapeThe shape of the tooltip panel.
backgroundColorThe background color of the tooltip panel.
contentColorThe color to apply to the contents of the tooltip panel.
contentPaddingPadding values for the content within the tooltip panel.
contentA composable function that defines the content of the tooltip.

TooltipPanel (with arrow)

ParameterDescription
modifierModifier to be applied to the tooltip panel.
arrowA composable function that receives TooltipArrowDirection and draws the arrow accordingly.
enterThe enter transition for the tooltip panel. Default is instant appearance.
exitThe exit transition for the tooltip panel. Default is instant disappearance.
contentA composable function that defines the content of the tooltip.