| name | d3-interactivity-and-tooltips |
| description | HTML/CSS/JS patterns for creating tooltips, conditional interactions based on data attributes, and cross-highlighting elements across different views (like a chart and a table). |
1. Tooltip HTML/CSS/JS Pattern
To create a dynamic tooltip, use a hidden HTML div that is styled with CSS and positioned dynamically using JavaScript mouse events.
HTML Pattern:
<div id="tooltip" class="tooltip"></div>
CSS Pattern:
.tooltip {
position: absolute;
opacity: 0;
pointer-events: none;
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-family: sans-serif;
font-size: 12px;
transition: opacity 0.2s;
}
JavaScript Pattern:
Bind mouseover, mousemove, and mouseout events to your D3 selection. Position the tooltip using event.pageX and event.pageY.
const tooltip = d3.select("#tooltip");
nodes.on("mouseover", function(event, d) {
tooltip.style("opacity", 1);
tooltip.html(`<strong>${d.name}</strong><br>Value: ${d.value}`);
})
.on("mousemove", function(event, d) {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY + 10) + "px");
})
.on("mouseout", function(event, d) {
tooltip.style("opacity", 0);
});
2. Conditional Interactions Pattern
Sometimes interactions (like tooltips) should only trigger for specific data points (e.g., skip entries missing certain fields). Wrap the logic inside your event listeners with a condition.
nodes.on("mouseover", function(event, d) {
if (d.type !== "ETF") {
tooltip.style("opacity", 1);
tooltip.html(`Ticker: ${d.ticker}<br>Market Cap: ${d.marketCap}`);
}
})
.on("mousemove", function(event, d) {
if (d.type !== "ETF") {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY + 10) + "px");
}
})
.on("mouseout", function(event, d) {
tooltip.style("opacity", 0);
});
3. Cross-Highlighting Pattern
To connect two different views (like a bubble chart and a table), assign common identifiers to both elements and toggle a specific CSS class (e.g., .selected) on click.
CSS Pattern:
.bubble.selected {
stroke: #000;
stroke-width: 3px;
}
.table-row.selected {
background-color: #ffff99;
font-weight: bold;
}
JavaScript Pattern:
Attach a click handler that removes the .selected class from all elements, then adds it back only to the elements matching the clicked data.
function handleSelection(event, d) {
d3.selectAll(".bubble").classed("selected", false);
d3.selectAll(".table-row").classed("selected", false);
d3.selectAll(".bubble")
.filter(nodeData => nodeData.ticker === d.ticker)
.classed("selected", true);
d3.selectAll(".table-row")
.filter(rowData => rowData.ticker === d.ticker)
.classed("selected", true);
}
d3.selectAll(".bubble").on("click", handleSelection);
d3.selectAll(".table-row").on("click", handleSelection);