Display on hover
The previous lesson explained how to create a Tooltip component written in html that locates itself at the right position, on top of the SVG area.
Now it's time to make it appear only on hover. The implementation looks a lot like what we've done for hover effects, so you'll likely find it straightforward!
What we're building
The tooltip from the previous lesson was always visible, but the heavy lifting was already done: component, styling, positioning. Now we just need to reveal it only when the user is hovering a marker.
The trick: an internal state that flips on hover. Here's the full result before we break it down:
import { useState } from "react"; import { Tooltip } from "./Tooltip"; import "./styles.css"; const width = 500; const height = 300; export default function App() { const [interactionData, setInteractionData] = useState(null); return ( <div style={{ position: "relative" }}> {/* SVG layer */} <svg width={width} height={height}> <circle cx={width / 2} cy={height / 2} r={30} fill="#4e79a7" onMouseEnter={() => setInteractionData({ xPos: width / 2, yPos: height / 2, name: "Hello tooltip", xValue: width / 2, yValue: height / 2, color: "#4e79a7", }) } onMouseLeave={() => setInteractionData(null)} /> </svg> {/* Tooltip layer */} <div style={{ position: "absolute", width, height, top: 0, left: 0, pointerEvents: "none", }} > <Tooltip interactionData={interactionData} /> </div> </div> ); }
Hover over the blue circle. Move away to dismiss the tooltip.
How it works: 3 small moves
The whole thing boils down to a single state that answers one question: which marker is the user currently hovering?
Fill it on onMouseEnter, clear it on onMouseLeave, and let the Tooltip component render from it.
useState? The useState lesson in module B is a quick refresher.1️⃣ A state for the active marker
We hold the currently hovered marker in a single piece of state. When nothing is hovered, the state is null.
Otherwise, it's an interactionData object with everything the tooltip needs to render. Shaped exactly like the prop the Tooltip component already expects, which is not a coincidence.
import { useState } from "react";
const [interactionData, setInteractionData] = useState(null);2️⃣ Fill the state on hover, clear it on leave
Attach onMouseEnter and onMouseLeave directly to each SVG marker. On enter, we push the marker's data into state. On leave, we reset to null.
<circle
cx={250}
cy={150}
r={30}
fill="#4e79a7"
onMouseEnter={() =>
setInteractionData({
xPos: 250,
yPos: 150,
name: "hello",
})
}
onMouseLeave={() => setInteractionData(null)}
/>onMouseLeave, the tooltip would linger forever once the cursor moves off the circle. The exit handler is as essential as the entry one.3️⃣ Render the tooltip from state
Our Tooltip component already returns null when its prop is null (remember the early-return from the previous lesson). So we just pass the state down and let the component do the right thing:
<div
style={{
position: "absolute",
width,
height,
top: 0,
left: 0,
pointerEvents: "none",
}}
>
<Tooltip interactionData={interactionData} />
</div>⚠️ Don't forget pointerEvents: "none" on the overlay. If the overlay catches the mouse, the onMouseEnter on the SVG shapes underneath will never fire, and the tooltip will never appear in the first place.
Oh no! 😱
It seems like you haven't enrolled in the course yet!
Join many other students today and learn how to create bespoke, interactive graphs with d3.js and React!
Enrollment is currently closed. Join the waitlist to be notified when doors reopen:
Or Login