Hello! Happy Samhain/Halloween!!! This a very spooky fast article where I would like to show you how I built a react tooltip on my latest side-project.
This is a simple Tooltip component, and even I know there are great libs out there, I'm always betting on building mine first before moving and add a new dependency to my project, let's go...
I'm using tailwindcss for this one, if you are not using tailwindcss in your React project please stop right now and go to https://tailwindcss.com/ and take a look, I have also a couple of starters on github for CRA and Nextjs you may want to clone for a quick start:
Nextjs -> https://github.com/alexandprivate/next-netlify-tailwind-starter
CRA -> https://github.com/alexandprivate/cra-tailwind-router-starter
Now do let's see the code
Full component
function Tooltip({ children, tooltipText }) {
const tipRef = React.createRef(null);
function handleMouseEnter() {
tipRef.current.style.opacity = 1;
tipRef.current.style.marginLeft = "20px";
}
function handleMouseLeave() {
tipRef.current.style.opacity = 0;
tipRef.current.style.marginLeft = "10px";
}
return (
<div
className="relative flex items-center"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<div
className="absolute whitespace-no-wrap bg-gradient-to-r from-black to-gray-700 text-white px-4 py-2 rounded flex items-center transition-all duration-150"
style={{ left: "100%", opacity: 0 }}
ref={tipRef}
>
<div
className="bg-black h-3 w-3 absolute"
style={{ left: "-6px", transform: "rotate(45deg)" }}
/>
{tooltipText}
</div>
{children}
</div>
);
}
A couple of clarifications, the tooltip always opens to the right in this case but you can always tweak the direction or even create a prop to control it
I'm using ref to avoid setting a state to show or hide the tooltip, these ways the component doesn't have to deal with re-renders
const tipRef = React.createRef(null);
and handling the show and hide events with onMouse API
function handleMouseEnter() {
tipRef.current.style.opacity = 1;
tipRef.current.style.marginLeft = "20px";
}
function handleMouseLeave() {
tipRef.current.style.opacity = 0;
tipRef.current.style.marginLeft = "10px";
}
There is a prop for the tooltip text and children to use this as a composition, so you may use the component like this
Now you just need to wrap an element where you want to show the tooltip at, for example on a Nextjs Link
<Tooltip tooltipText="Shop Insights">
<Link href="/insights">
<a>
<AiOutlineAlert className="text-3xl" />
</a>
</Link>
</Tooltip>
And you will get something like this...
Happy coding and don't eat too many candies today!
Top comments (4)
Hi Alex, thank you for this beautiful piece of code. Here I leave the code ready to receive in which position to appear.
`import { useRef } from 'react'
import propTypes from 'prop-types'
const Tooltip = ({ children, tooltipText, orientation = 'right' }) => {
const tipRef = useRef(null)
}
Tooltip.propTypes = {
orientation: propTypes.oneOf(['top', 'left', 'right', 'bottom']),
tooltipText: propTypes.string.isRequired,
}
export default Tooltip`
It's a lot easier to use the HTML
title
attribute:Hi there, LOL, easier? Sure. Better? Absolutely not, you can style title, not ui or behaviour, also title has a default delay to show up, we can say title is the most primitive way of tooltip natively support by the browser, so if you can improve that do it 👍
Fantastic. Thank you!