d3-tip

Configurable, positioned tooltips for D3.js SVG data visualizations.

Library
npm
v0.9.1
1,209stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity0
Maintenance20
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
63/100Good
Architecture72
Code Quality35
Innovation68
Learning Curve75

d3-tip is a small plugin for D3.js that adds tooltips to SVG-based charts and visualizations. Rather than reimplementing hover-triggered popups for every chart, you initialize a single tip instance, bind it to your visualization with .call(tip), and wire it to mouseover/mouseout events to show contextual HTML content anchored to the hovered shape.

The API follows D3’s own selection conventions closely: tip.attr() and tip.style() proxy directly to the underlying tooltip DOM node, tip.direction() picks from eight compass-point positions (n, s, e, w and the four diagonals), and tip.html() accepts either a static string or a per-datum function, mirroring how D3 selections already bind data to content. It ships as a lightweight ES module (~6kb, ~2kb gzipped) with no dependencies beyond d3-collection and d3-selection, making it easy to drop into any existing D3 v4+ project without pulling in a heavier UI toolkit.

What You Get

  • A d3.tip() factory that returns a chainable tooltip instance, initialized the same way as a D3 selection
  • Eight built-in compass-point directions (n, s, e, w, ne, nw, se, sw) with screen-coordinate positioning computed from the target SVG shape’s bounding box
  • tip.attr() and tip.style() proxies that pass straight through to the underlying tooltip DOM node, so any CSS class or inline style can be applied without touching d3-tip internals
  • tip.html() accepting either a static string or a per-datum callback function, so tooltip content can reflect the bound data for each shape
  • tip.show() / tip.hide() methods designed to be wired directly to mouseover/mouseout (or similar) event handlers
  • A tip.destroy() method for cleanly removing the tooltip node from the DOM when a visualization is torn down

Common Use Cases

  • Showing a data value or label when hovering over bars in a D3 bar chart
  • Displaying contextual details for circles, points, or markers in scatter plots and bubble charts
  • Annotating geographic regions on a D3-rendered choropleth or map with per-region stats on hover
  • Adding lightweight interactivity to dashboards built directly on raw D3 rather than a higher-level charting library
  • Prototyping or teaching D3 visualizations where a full charting framework would be overkill

Under The Hood

Architecture The entire plugin lives in one flat, closure-based factory in index.js (~250 lines): calling the exported default function returns a tip object whose public methods (show, hide, attr, style, direction, offset, html, rootElement, destroy) close over private state (the current direction/offset/html functions, the tooltip’s DOM node, the target SVG element, and a cached SVGPoint). Direction resolution is dispatched through a d3-collection map of eight named callback functions (directionNorth, directionSouthEast, etc.), each computing tooltip placement from getScreenBBox(), a private helper that walks up to the nearest element exposing getScreenCTM() and transforms its bounding box into screen coordinates. This is the classic D3 plugin shape (the same factory-closure pattern used by d3.dispatch and D3’s own scales) rather than a class hierarchy, and because the tip is a leaf dependency invoked as d3.tip() with no plugin registration or DI, changing its internals has no ripple effect on consuming visualization code beyond its public chainable API.

Tech Stack Runtime dependencies are minimal: d3-collection (^1.0.4, for the map structure) and d3-selection (^1.3.0, for DOM/SVG selection). The published dist/index.js (the package’s main) is built from the ES module source via Rollup (rollup.conf.js), while module/jsnext:main point straight at the untranspiled index.js. Development tooling is ESLint (eslint-config-airbnb-base) run through a Makefile and CircleCI (circle.yml), plus a bower.json retained for legacy Bower-based distribution alongside npm. The code targets browser DOM/SVG APIs directly (document.body, SVGElement, getScreenCTM) with no transpilation target beyond what Rollup’s ES module bundling provides.

Code Quality No test files or test directory exist anywhere in the repository, and the test npm script is a stub that simply exits with an error (“no test specified”) rather than running any suite. ESLint is configured and run in CI, giving some static-analysis coverage, but there is no type system — plain JavaScript with no TypeScript definitions or JSDoc type annotations. Error handling is implicit rather than explicit: for example, the tip factory silently no-ops if it can’t find an SVG node, with no thrown errors or logging. Naming is consistent and D3-idiomatic throughout (tip.show, tip.hide, tip.attr mirror D3 selection method names).

API Design The public API deliberately mirrors D3’s own selection-style getter/setter chaining, so tip.attr('class', 'd3-tip').html(fn) reads exactly like a D3 selection call and requires no new mental model for anyone already writing D3 code. Getting a tooltip working takes one line to create the instance, one .call(tip) to bind it to a visualization, and two event handlers to show/hide it — very low boilerplate for the value it provides. Documentation is split into focused, single-topic pages (initializing, showing/hiding, styling, positioning, updating content) backed by eight runnable HTML examples covering bars, circles, CSS transitions, and RequireJS usage, giving newcomers a clear, example-driven path in even though the docs pages themselves are individually thin.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search