Search justacoding.blog. [Enter] to search. Click anywhere to close.

August 22nd, 2022

Build Your Own React Tooltip Component

Tooltips can be really useful.

Essentially, the tooltip is a message or some other piece of information that displays upon hovering (or alternatively, clicking) some element with the user interface. Tooltips can be used to portray important information to the user in a clean and easily digestible manner.

In this short guide, we’ll create our very own Tooltip component using React!

You can refer to the fully-functional example here: React Tooltip Component.

How our React Tooltip component will actually work

Let’s briefly recap what this component will do:

  • It’ll render an icon (for instance a ? icon)
  • On hovering the icon, a tooltip (or message) will display
  • The tooltip will display text defined by the user, and the tooltip element itself can be positioned as required, too (for instance the text could show above the ? icon, or below it)
  • It’ll also be possible to activate the tooltip via clicking as opposed to hovering (which is the default behaviour for our tooltip component)

Building a simple tooltip component such as this one is a great task for React beginners to undertake. We’ll cover some important React fundamentals during this build.

Building the tooltip component

First thing’s first, we’ll be needing some markup for our component.

The JSX structure

Here’s the JSX returned by our React tooltip component:

<div className="tooltipContainer" {...interactionProps}>
    {customIcon ? customIcon : <div className="tooltipIcon">?</div>}
    {isVisible && (
        <div
            className="tooltipText"
            style={{
                 top: topOffset,
                 left: leftOffset
            }}
        >
             {children}
        </div>
    )}
</div>

Some simple CSS

And here’s the main CSS that’s responsible for correctly positioning each of the tooltip elements:

.tooltipContainer {
    position: relative;
    display: inline-block;
}

.tooltipIcon {
    width: 30px;
    height: 30px;
    background: #dadada;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 15px;
    cursor: pointer;
}

.tooltipText {
    position: absolute;
    padding: 6px;
    border-radius: 3px;
    z-index: 1000;
}

The most important thing here is the position: relative style on the tooltipContainer element.

We need relative positioning here as the tooltip message itself will be positioned absolutely – we don’t want to interact with or push around any other elements on the page! The tooltip text should overlay any and all content around it.

It’s for the same reason that we’re giving the tooltipText element a high z-index — it should overlay content underneath it.

You’ll notice we aren’t setting any margins (top or left) on tooltipText yet, also.

We’ll handle this dynamically in the component itself – and thus allow the user to override these default margins as required.

This will allow them to position the tooltip exactly as they wish, on a per-tooltip basis – ultimately allowing a greater ease of control.

What’s children for here?

You may have noticed that our tooltip component (SuperSimpleTooltip) receives a prop called children.

This is a special prop.

Essentially, children here refers to whatever element(s) we wrap with the parent component:

<SuperSimpleTooltip>
    {/* CHILDREN */}
</SuperSimpleTooltip>

When learning React, it’s important to understand the importance of this special prop. It allows you to more easily construct components together, and this is one of the key concepts/patterns of React in general.

Building (or composing) components that can work together, like building blocks. Modular in nature.

We’re using the children prop to supply the “inner content” ie. whatever the user sees when they hover the tooltip icon.

This tooltip content can be anything at all. It could even be it’s own component that’s used elsewhere, outside of the tooltip component altogether.

Regardless of this, our tooltip component can always “wrap” the inner component (whatever this may be) and achieve the desired behaviour due to how we’ve composed this component to begin with:

<SuperSimpleTooltip>
    <TooltipInformation text="" />
</SuperSimpleTooltip>

Controlling the tooltip visibility

Now the basic markup is in place, let’s move on to actually adding some functionality to our React tooltip component.

As you can see, we’ll be making use of an isVisible boolean here (read more about the useState hook, if you are unfamiliar).

const [isVisible, setIsVisible] = useState(false)

The premise is fairly simple. Once the user clicks (or hovers) our tooltip icon – set isVisible to true. Once they click again (or hover away), set isVisible to false.

isVisible is directly responsible for showing and hiding the the actual tooltip message.

Accompanied with the relevant positioning/structural elements we’ve already got in place, this interaction forms the basis of our React tooltip component

Adding the various user interactions (click/hover)

As stated in the introduction, there will be two modes for the tooltip component: click and hover.

hover is the default mode.

To handle this, we can make use of a simple prop – mode. The user can pass a click or hover prop respectively.

Depending on which mode is required, we can use a simple switch statement like this:

switch (mode) {
    case Interactions.Hover:
        interactionProps = {
            onMouseOver: () => setIsVisible(true),
            onMouseLeave: () => setIsVisible(false)
        }
        break
    case Interactions.Click:
        interactionProps = {
            onClick: () => setIsVisible((prev) => !prev)
        }
    break
}

This will apply the relevant props to the tooltipContainer element, which will in turn allow the user to interact with the tooltip in the required manner.

Allowing the user to position the tooltip element

I’ve opted for a rudimentary approach here – just allow the user to supply topOffset and leftOffset props to control the positioning of each individual tooltip.

It’s possible to dynamically position the tooltip ie. always center it, either above or below the icon, but for now – I’m just affording the user the ability to manually control this.

<div
    className="tooltipText"
    style={{
        top: topOffset,
        left: leftOffset
    }}
>

It’s as simple as setting the top and left margins on the tooltipText element.

Each tooltip can be placed accordingly via the use of these props. The tooltip will, by default, be positioned towards the top left of the relatively-position element.

Do “something” on show/hide

As a little piece of extra functionality – we can add the facility to do something once the tooltip changes visibility, using the useEffect hook:

useEffect(() => {
        if (isInitialRender.current) {
            isInitialRender.current = false
        } else {
            if (isVisible && onOpen) {
                onOpen()
            }
            if (!isVisible && onClose) {
                onClose()
            }
        }
}, [isVisible, onOpen, onClose])

Essentially, functions an be passed in via the onOpen and onClose props.

These functions are invoked, respectively, once the tooltip is opened and/or closed.

A potential use-case of this may be to control the visibility of an overlay screen upon activating the tooltip, for example. The component itself doesn’t implement this — but this mechanism allows the user to control this as they please.

What’s useRef doing here?

We only want to fire off the onOpen/onClose functions when the visibility of the tooltip actually changes through regular interactions. We don’t want to trigger these functionalities upon the initial render of our React tooltip component – that’s what we’re handling in the code above.

Our useRef value is initialised via the following:

let isInitialRender = useRef(true)

With this, we have a way to identify the initial render.

You can see that the useRef hook is used to help achieve this behaviour.

And based on this (whether it’s the initial render or not) we can choose to ignore the onOpen/onClose functionalities (if they have been provided, that is).

Further functionalities that can be added

As you can see, this is an extremely simple tooltip component.

It is, however, a good base to add more functionalities as required!

Here are a few ideas:

Dynamically center the tooltip message

It may be more convenient for the tooltip message to be, by default, “centered” with regards to the tooltip icon.

This means that whatever the width – it’ll always be positioned centrally on the horizontal axis.

This default behaviour/positioning could then be overridden via props (similar to what we are doing now), so it’s position can be tweaked as required.

Hide the tooltip after x seconds

It may be a fairly useful option to hide the tooltip after a given interval.

To do this, you can pass a prop to our React tooltip component – like hideAfterSeconds or something similar.

If the user supplies a value of 2 for this prop – the tooltip would fade away after 2 seconds of being first revealed.

You can make use of the setTimeout method for this.

In closing

Thanks for following along!

I hope this React tooltip component guide has been useful in some way, and that’s it helped you build your very own tooltip component in React.

You can find similar articles & guides similar to this one in the Code Examples section.

Thanks for reading!

Have any questions? Ping me over at @justacodingblog
← Back to blog