Create a React-Bootstrap Overlay ToolTip with Arrow and Custom Position

React-Bootstrap has two options for tooltips: an Overlay component that can have a manually constructed tooltip (for complex requirements) or a simpler OverlayTarget and Tooltip. The example in the docs for the Overlay is good. In this tutorial, we will construct a ToolTip using the Overlay component and add a pointer arrow and custom position.

Here’s an example of what we will build:

React Bootstrap Top ToolTip with Arrow
React Bootstrap Top ToolTip with Arrow

The code for positioning and the arrow is different depending on which side of the button the tooltip is on, so I will show all four directions below.

It also seems that arrowProps does not work for creating a pointer…or at least I got a TypeScript warning when trying to use it. Instead, I have constructed an arrow with CSS and it works great.

How to Create a Quick Bootstrap-React ToolTip with OverlayTrigger and Tooltip Components

The easy way to create a Tooltip is by wrapping the target component with an OverlayTrigger component. This handles the hover detection and adds an arrow automatically to the Tooltip:

const renderTooltip = (props: any) => (
  <Tooltip id="button-tooltip" {...props}>
    Simple tooltip
  </Tooltip>
);

return (
<OverlayTrigger
  placement="top"
  delay={{ show: 200, hide: 200 }}
  overlay={renderTooltip}
>
  <Button variant="danger">
    Hover Button
  </Button>
</OverlayTrigger>
)
React-Bootstrap Tooltip and OverlayTrigger Example
React-Bootstrap Tooltip and OverlayTrigger Example

The benefit of using these components to create the tooltip is that they are easy and automatically make use of the Bootstrap style variables. The drawback is it’s a bit heavier of a DOM component. Notice that there are three divs to render this tooltip instead of just one if we just use an Overlay component.

React Bootstrap Tooltip DOM
React Bootstrap Tooltip DOM

We can still custom style the tooltip and arrow. Here are the selectors used for making the tooltip green:

.bs-tooltip-top .tooltip-arrow::before {
  border-top-color: green;
}

.tooltip-inner {
  background-color: green;
}

And here’s the result:

Custom React-Bootstrap Tooltip Background and Arrow Color
Custom React-Bootstrap Tooltip Background and Arrow Color

How to Create a React-Bootstrap ToolTip with the Overlay component

The React Bootstrap tooltip requires two pieces of information in order to render in the correct location and time:

  • deA ref for the component it is supposed to render near
  • A state value for when to show or hide

In the code below, we can see these values being passed to the ToolTipTop:

//BRTooltip.tsx
<Button variant="danger" ref={target} onMouseOver={() => setShow(!show)} onMouseOut={() => setShow(!show)}>
  Hover Button
</Button>
<ToolTipTop current={target.current} show={show} />

Then inside of our tooltip the overlay consumes these values. I made the ToolTipTop a separate file so that I could easily have a bottom, left, and right tooltip as well with some shared code:

ToolTipTop.tsx
export default function ToolTipTop(props: { current: any, show: boolean }) {
  return (
    <>
      <Overlay target={props.current} show={props.show} placement="top">
        {({ placement, arrowProps, show: _show, popper, ...props }) => (
          <div
            className="tooltip"
            {...props}
            style={{
              ...props.style,
              bottom: "1rem"
            }}
          >
            ToolTip Top
          </div>
        )}
      </Overlay>
    </>
  );
}

The most interesting parts of the code above are placement, bottom: "1rem", and className: "tooltip". In order to have space between the tooltip and the button it references, I had to add some bottom positioning to “move the tooltip up”.

Notice I also passed arrowProps. This wasn’t used and didn’t seem to work right, but I had to include it otherwise React printed an error in the console.

Inside of the tooltip class I have this styling code:

.tooltip {
  background-color: red;
  padding: 2px 10px;
  color: white;
  border-radius: 4px;
}

Here’s the React Bootstrap ToolTip we’ve created so far:

React Bootstrap ToolTip Example
React Bootstrap ToolTip Example

How to Add an Arrow and Custom Position to the React-Bootstrap ToolTip Top

We can change the custom positioning of the Tooltip simply by changing the positioning. In the case of the top arrow, we need to modify the bottom styling. This has to be done through inline styling since Bootstrap is adding inset values inline:

React-Bootstrap ToolTip positioning
React-Bootstrap ToolTip positioning

In the styling above I added a value of bottom: "2rem". Notice how that was injected into the inset value.

We can also customize the position through the built-in placement prop (as seen in the Overlay docs). This has a limited range of values, but can be augmented by the inline style positioning seen above.

React Bootstrap Overlay Placement Prop
React Bootstrap Overlay Placement Prop

Next we want to add an arrow to the bottom of the tooltip. I created an arrow by targeting the after pseudo-element of the div. Here’s the code, which we will explore in detail:

//shared tooltip styling in BRToolTip.scss

.tooltip:after {
  content: "";
  display: block;
  position: absolute;
  border-style: solid;
  border-width: 8px;
}

//tooltip top specific styling (ToolTipTop.scss)

.tooltip:after {
  border-color: red transparent transparent transparent ;
  left: calc(50% - 8px);
}

I created a separate file for each ToolTip (top, right, bottom, left) because they each have a bit of unique code. However, most code and styling is common among all four.

In file BRToolTip.scss, I have common .tooltip:after styling. These are the necessary properties, otherwise the arrow does not render correctly:

  • content
  • display: block
  • position: absolute
  • border-style: solid
  • border-width: 8px (this can change depending on how thick of an arrow you want)

The arrow is created by making a filled content area. The border-width is actually short for border-top-width, border-right-width, and so on. Each of these border sections is filling the content with a triangle. For example, the border-top-width is creating a downward pointing triangle.

Next, we need to make only one of these four triangles visible through a border color. Since we want a downward pointing arrow for our ToolTipTop, we want only the top border to be filled while the rest are transparent:

border-color: red transparent transparent transparent ;

Then we add some left positioning to center the pseudo-element:

left: calc(50% - 8px);

This post by Calvin Pak was very helpful in constructing these arrows.

We can see the effects in the screenshot below.

React Bootstrap Overlay Tooltip DOM
React Bootstrap Overlay Tooltip DOM

In the below sections I give the specific code for each arrow direction.

Bootstrap has lots of border customization options.

How to Right Position a React-Bootstrap ToolTip with Arrow

We can right position a React Bootstrap Tooltip with a few tweaks to our JSX:

export default function ToolTipRight(props: { current: any, show: boolean }) {
  return (
    <>
      <Overlay target={props.current} show={props.show} placement="right">
        {({ placement, arrowProps, show: _show, popper, ...props }) => (
          <div
            className="tooltip"
            {...props}
            style={{
              ...props.style,
              left: "1rem"
            }}
          >
            ToolTip Right
          </div>
        )}
      </Overlay>
    </>
  );
}

First, we passed placement="right". Second, we customize the position with left: "1rem" inline styling.

Next we need to add styling to customize where the arrow points. Remember most of our tooltip:after styling is in a shared file. Here’s the code that is specific to ToolTipRight:

//ToolTipRight.scss

.tooltip:after {
  top: calc(50% - 8px);
  right: 100%;
  border-color: transparent red transparent transparent;
}

Notice here we position the after pseudo-element (the arrow). Then we need to make the right border triangle red while the other three border sides are transparent.

Here’s what we create:

React Bootstrap ToolTip Right with Arrow
React Bootstrap ToolTip Right with Arrow

Here’s how to add Tooltip on React-Bootstrap Table Cell Hover.

How to Bottom Position a React-Bootstrap ToolTip with Arrow

To bottom position the Tooltip, we make the following changes to our JSX:

  • placement="bottom" directs the Overlay where to appear
  • top: "1rem" inline styling customizes the spacing between the top of the tooltip and the bottom of the button

Here’s the custom styling we need:

//ToolTipBottom.scss

.tooltip:after {
  left: calc(50% - 8px);
  bottom: 100%;
  border-color: transparent transparent red transparent;
}

First we position the arrow as needed for it to appear on top of the tooltip and centered. Next we make only the bottom side of the border red while the top, right, and left are transparent.

How to Left Position a React-Bootstrap ToolTip with Arrow

To left position the Tooltip, we make the following changes to our JSX:

  • placement="left" directs the Overlay where to appear
  • right: "1rem" inline styling customizes the spacing between the right of the tooltip and the left of the button. An easy way to think of this is, “I want the arrow on the right of the tooltip”, so we use the right value.

Here’s the custom styling we need:

//ToolTipLeft.scss

.tooltip:after {
  top: calc(50% - 8px);
  left: 100%;
  border-color: transparent transparent transparent red;
}

First we position the arrow as needed for it to appear to the right of the tooltip and centered. Next we make only the left side of the border red while the top, right, and bottom are transparent.

Resources

We can create incredible React Bootstrap custom components like this “TextField”. I hope my tutorials show that if you can dream it up, you can create it.

I also recommend the MUI ToolTip, which is easy to use and highly customizable.

Here is the full code for the shared BRToolTip component and the subcomponent ToolTipTop. Use the above code snippets to modify for right, left, and bottom tooltips. Check out how to add a border to the ToolTip and arrow.

//BRToolTip.tsx

import { useRef, useState } from "react";
import Button from "react-bootstrap/Button";
import "./BRToolTip.scss";
import ToolTipTop from "./ToolTipDirections/ToolTipTop";
//import ToolTipLeft from "./ToolTipDirections/ToolTipLeft";
//import ToolTipRight from "./ToolTipDirections/ToolTipRight";
//import ToolTipBottom from "./ToolTipDirections/ToolTipBottom";

export default function BRToolTip() {
  const [show, setShow] = useState(false);
  const target = useRef(null);

  return (
    <>
      <Button variant="danger" ref={target} onMouseOver={() => setShow(!show)} onMouseOut={() => setShow(!show)}>
        Hover Button
      </Button>
      <ToolTipTop current={target.current} show={show} />
      {/* <ToolTipLeft current={target.current} show={show} /> */}
      {/* <ToolTipRight current={target.current} show={show} /> */}
      {/* <ToolTipBottom current={target.current} show={show} /> */}
    </>
  );
}

//BRToolTip.scss

@import "bootstrap/scss/bootstrap";

.tooltip {
  background-color: red;
  padding: 2px 10px;
  color: white;
  border-radius: 4px;
}

.tooltip:after {
  content: "";
  display: block;
  position: absolute;
  border-style: solid;
  border-width: 8px;
}

//ToolTipTop.tsx

import React from "react";
import Overlay from "react-bootstrap/Overlay";
import "./ToolTipTop.scss";

export default function ToolTipTop(props: { current: any, show: boolean }) {
  return (
    <>
      <Overlay target={props.current} show={props.show} placement="top">
        {({ placement, arrowProps, show: _show, popper, ...props }) => (
          <div
            className="tooltip"
            {...props}
            style={{
              ...props.style,
              bottom: "1rem"
            }}
          >
            ToolTip Top
          </div>
        )}
      </Overlay>
    </>
  );
}

//ToolTipTop.scss

.tooltip:after {
  border-color: red transparent transparent transparent ;
  left: calc(50% - 8px);
}
Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.