React Clean UI
Interaction

Tooltip

Display helpful information when users hover over an element.

Tooltip demonstration

Tooltips provide additional context for buttons, text, and other interface elements without taking up permanent space. They appear when the user hovers over the wrapped element. The tooltip can display either simple text or custom React content.

Basic Usage

Wrap any single UI element with a Tooltip and provide the tooltip content.

Loom Previewv0.13.2

The wrapped element can be a library component or a native Roblox element such as <frame> or <imagebutton>. Any MouseEnter / MouseLeave handlers the child already has are kept and run first.

<Tooltip content="Health potion">
    <imagebutton
        Size={UDim2.fromOffset(48, 48)}
        Image="rbxassetid://0000000"
        Event={{
            MouseEnter: () => print("Hovered slot"),
        }}
    />
</Tooltip>

Placement

Use the placement prop to control where the tooltip appears relative to its target.

<Tooltip content="Above" placement="Top">
    <Button text="Top" />
</Tooltip>

<Tooltip content="Below" placement="Bottom">
    <Button text="Bottom" />
</Tooltip>

<Tooltip content="Left" placement="Left">
    <Button text="Left" />
</Tooltip>

<Tooltip content="Right" placement="Right">
    <Button text="Right" />
</Tooltip>

<Tooltip content="Centered" placement="Center">
    <Button text="Center" />
</Tooltip>

"Center" positions the tooltip directly over the middle of its target instead of pointing at an edge, and hides the pointer arrow.

Staying on screen

The tooltip measures itself before it appears and keeps itself on screen, clear of the Roblox topbar (the core buttons in the top-left corner):

  • The side you pick is the preferred side. If the tooltip doesn't fit there but fits on the opposite side, it opens on the opposite side instead: a "Top" tooltip on a button near the top of the screen opens below it. If it fits on neither side, it uses whichever has more room.
  • It then slides along the edge to stay on screen, and the pointer moves the other way so it still points at the middle of the target.
  • "Center" never changes side.

Use "Auto" to let the tooltip choose. It already picks the side with the most room: it prefers a side where it fits and stays centred on the target, then the side with the most spare space, and if no side fits, the side with the most room. Ties go to Top, then Bottom, Right and Left.

<Tooltip content="Opens wherever it fits best" placement="Auto">
    <Button text="Inventory" />
</Tooltip>

Intent

Tooltips support the standard intent colors.

<Tooltip
    content="Operation completed successfully!"
    intent="success"
>
    <Button intent="success" text="Success" />
</Tooltip>

Custom Content

The content prop can contain any React element, allowing you to build richer tooltips.

<Tooltip
    placement="Right"
    intent="warning"
    content={
        <Container>
            <VStack spacing="None">
                <HStack>
                    <Icon icon="hand-peace-o" />
                    <Text text="With an Icon!" variant="heading" />
                </HStack>

                <Text text="You can place any React UI inside a tooltip." />
            </VStack>
        </Container>
    }
>
    <Button text="Custom Tooltip" />
</Tooltip>

Disabling

Set disabled to stop the tooltip from showing. If it is already open, it fades out.

<Tooltip content="Drag to move" disabled={isDragging}>
    <Button text="Item" />
</Tooltip>

Toggling disabled does not change the wrapped element: it is not remounted and keeps its ref and event handlers. This makes it safe to toggle while the element sits under a Draggable.Handle, even in the middle of a drag.

Controlled visibility

Pass open to control visibility yourself. While open is set, hovering no longer shows or hides the tooltip. Leave it undefined for the normal hover behaviour.

<Tooltip content="Click here to continue" open={tutorialStep === 3}>
    <Button text="Continue" />
</Tooltip>

disabled always wins: a tooltip with disabled set stays hidden even when open is true.

Interactive tooltips

By default a tooltip closes as soon as the pointer leaves its target, so you can't reach anything inside it. Set interactive to let the pointer move from the target onto the tooltip and use controls in its content.

Loom Previewv0.13.2

Once nothing keeps an interactive tooltip open, it waits theme.components.tooltip.closeDelay seconds (0.15 by default) before closing, giving the pointer time to cross the gap. Moving back onto the target or the tooltip cancels the close. Non-interactive tooltips still close immediately.

An interactive tooltip is Active, so clicks on it don't reach whatever is behind it.

Pin on press

Set pinOnPress to let a left click or tap on the target pin the tooltip open. Pressing the target again unpins it, and so does pressing anywhere on the tooltip itself.

<Tooltip content="Pinned until you press again" pinOnPress>
    <Button text="Details" />
</Tooltip>

If the pointer is still over the target or the tooltip when it is unpinned, it stays open until the pointer leaves.

Long press

Set longPress to open the tooltip on touch devices by holding a finger on the target. After theme.components.tooltip.longPressDelay seconds (0.5 by default) it opens, and stays open until the finger is lifted.

<Tooltip content="Restores 50 health" longPress pinOnPress>
    <imagebutton Size={UDim2.fromOffset(48, 48)} Image="rbxassetid://0000000" />
</Tooltip>

A touch released before the delay counts as a tap. With pinOnPress also set, a short tap toggles the pin (on release), and a long press shows the tooltip only while held. Without pinOnPress, a short tap does nothing. Mouse clicks always follow pinOnPress.

When pinOnPress or longPress is set, a MouseEnter caused by touch is ignored. Mobile fires MouseEnter on a tap without a matching MouseLeave, which would otherwise leave the tooltip stuck open.

interactive, pinOnPress and longPress are all ignored while open is set.

Nested tooltips

A Tooltip can be placed inside another tooltip's content. While the inner tooltip is open, it keeps the outer one open, but only if the outer tooltip is interactive or pinOnPress. When the inner tooltip closes, the outer one closes too (after its own closeDelay) unless something else keeps it open.

<Tooltip
    interactive
    content={
        <Tooltip interactive content={<Button text="Confirm" />}>
            <Button text="More options" />
        </Tooltip>
    }
>
    <Button text="Menu" />
</Tooltip>

Only the topmost tooltip reacts to the pointer. When the pointer is over an open interactive tooltip, any target underneath it (at the same or a shallower nesting level) is treated as covered: hovering it doesn't open its tooltip, a hover-only tooltip on it closes, and presses on it are ignored. Once the pointer leaves the covering tooltip, a target still under the pointer opens again. Only interactive tooltips cover targets, so ordinary tooltips (for example the "Center" tooltips on chart segments) don't block their neighbours.

Limitations

  • Pressing anything inside a pinned tooltip, including a button in its content, unpins it.
  • A long press is not cancelled when the finger moves. It stays open until the finger is lifted, even if it slides off the target.
  • Tapping outside a pinned tooltip does not close it. Press the target or the tooltip to unpin.
  • pinOnPress with placement="Center" is unreliable. Use a side placement for pinned tooltips.

Props

PropTypeDefaultDescription
contentstring | React.ReactNodeRequiredThe content displayed inside the tooltip.
placement"Top" | "Bottom" | "Left" | "Right" | "Center" | "Auto""Top"The preferred side. Flips to the opposite side when it doesn't fit. "Auto" picks the best side.
intentIntent"primary"Applies one of the standard intent color schemes.
spacingSpacingTheme defaultControls the internal padding of the tooltip.
disabledbooleanfalsePrevents the tooltip from showing and hides it if open. Overrides open.
openboolean—Controls visibility directly. When set, hover is ignored.
interactivebooleanfalseLets the pointer move onto the tooltip and interact with its content. Ignored when open is set.
pinOnPressbooleanfalseA click or tap on the target pins the tooltip open; pressing again (or pressing the tooltip) unpins it. Ignored when open is set.
longPressbooleanfalseOn touch, holding a finger on the target shows the tooltip while held. Ignored when open is set.
childrenReact.ReactElementRequiredThe element that triggers the tooltip when hovered. Can be a component or a native element.

Behaviour

  • The tooltip is rendered through the nearest overlay provider, so it appears above surrounding content and is not clipped by the target's ancestors. Without an overlay provider it never renders.
  • While visible, the tooltip follows its target if the target moves or resizes, and places itself again if its content or the screen changes size.
  • The tooltip keeps theme.components.tooltip.edgeMargin pixels (8 by default) from the screen edges and from the bottom of the Roblox topbar. This works whether or not the ScreenGui holding the overlay sets IgnoreGuiInset.
  • Tooltips inside a Draggable's drag preview never open, and tooltips inside the element being dragged close for the duration of the drag.
  • After being suppressed (by disabled or a drag), a hover-driven tooltip does not pop back open on its own. It reopens on the next hover. Suppression also clears any pin or long press.
  • Interactive and pinOnPress tooltips are Active, so clicks on them don't pass through to elements behind them.
  • The popup always sizes to its content. Size props (Size, width, height, minWidth, maxWidth, minHeight, maxHeight) are currently ignored.

Theme values

The tooltip uses values from theme.components.tooltip for:

  • fadeDuration — the fade in/out duration in seconds. 0 disables the fade.
  • pointerSize — the size of the pointer arrow in pixels. 0 hides it.
  • edgeMargin — the minimum gap between the tooltip and the screen edges and topbar. Default 8.
  • closeDelay — seconds an interactive tooltip waits before closing once nothing keeps it open. Default 0.15. Not used by non-interactive tooltips.
  • longPressDelay — seconds a touch must be held on a longPress target before the tooltip opens. Default 0.5.
  • spacing — the default internal padding.
  • boxShadow — an optional drop shadow around the tooltip.
  • intents — per-intent background, border and text colours.

These values can be changed by providing a custom Clean UI theme.

GitHub Repository

On this page