Introducing visx from Airbnb
By: Chris C Williams
Tags: React, Typescript, Visualization, Open Source, D3js

After 3 years of development, 2.5 years of production use at Airbnb, and a rewrite in TypeScript we are excited to announce the official 1.0 release of visx (formerly vx). You can find the project on GitHub and browse documentation and examples on airbnb.io.

At Airbnb, we made it a goal to unify our visualization stack across the company, and in the process we created a new project that brings together the power of D3 with the joy of React. Here are the advantages of visx:

Keep bundle sizes down. visx is split into multiple packages. Start small and use only what you need.

visx is split into multiple packages. Start small and use only what you need. Un-opinionated on purpose. Bring your own state management, animation library, or CSS-in-JS solution. Odds are good your React app already has an opinion on how animation, theming, or styling is done. visx is careful not to add another one and integrates with all of them.

Bring your own state management, animation library, or CSS-in-JS solution. Odds are good your React app already has an opinion on how animation, theming, or styling is done. visx is careful not to add another one and integrates with all of them. Not a charting library. As you start using visualization primitives, you’ll end up building your own charting library that’s optimized for your use case. You’re in control.

And most importantly — it’s just React. If you know React, you can make visualizations. It’s all the same standard APIs and familiar patterns. visx should feel at home in any React codebase. We’re excited to see what you build with it!

The Problem: Visualization for Frontend Developers

Data visualization is increasingly relevant to more people from varied backgrounds, and that diversity necessitates visualization authoring frameworks that cater to the skills and needs of those individuals.

One such group of authors are frontend developers, who are increasingly tasked with creating visualizations for the web. A wide range of great libraries and frameworks for authoring web-based visualizations are available — from D3, Highcharts, Plotly, ECharts, Victory, G2, Recharts, react-vis, vega, vega-lite, to Semiotic and so on. However, upon evaluating over a dozen existing libraries for use at Airbnb, we found that most fall short in at least one of three areas that our frontend developers value:

Learnable. (how much learning is required to build and maintain a visualization) — Most frontend engineers are not visualization experts, and the ramp up time or cost of context switching for D3’s imperative API or vega’s custom grammar are non-trivial in a large organization. Ideally, engineers should be able to learn a visualization library as quickly as other frontend packages.

(how much learning is required to build and maintain a visualization) — Most frontend engineers are not visualization experts, and the ramp up time or cost of context switching for D3’s imperative API or vega’s custom grammar are non-trivial in a large organization. Ideally, engineers should be able to learn a visualization library as quickly as other frontend packages. Expressive. (is it possible to create almost anything you can imagine?) — To use a single visualization framework across a large organization, it needs to support both simple charts — say for Airbnb.com — and highly custom visualizations for internal data products. Should your design capabilities be constrained due to chart library limitations? We don’t think so.

(is it possible to create almost anything you can imagine?) — To use a single visualization framework across a large organization, it needs to support both simple charts — say for Airbnb.com — and highly custom visualizations for internal data products. Should your design capabilities be constrained due to chart library limitations? We don’t think so. Performant. Frontend developers who are building production applications — like Airbnb.com — must be able to optimize speed and bundle sizes. One-size fits all chart frameworks with built-in animations, custom styling, and special event handling may not be desirable and bloat bundle sizes.

Others have noted that there is often a direct tradeoff between expressivity and learnability in visualization tooling, so how could we possibly create a library that achieves high marks across those dimensions and also be performant? One word: React.

The Solution: Low-level React-centric Visualization Primitives

In recent years, React has become a mainstream web framework in part because it has a highly readable, declarative API that promotes clean code and maintainability. React is familiar to many frontend developers and there are extensive resources for performance tuning and optimizing React applications. Leveraging React and its ecosystem would provide learnability and performance, and a low-level, modular API would deliver expressivity.

When describing this vision, two common questions arise:

“Why not just use D3 — which is highly expressive — inside a React app? “

You can! But because D3 and React both want to own DOM manipulation, we’ve found that it’s best to only use D3 for the math and React for the DOM because two mental models for updating the DOM opens the door for bugs to sneak in. However, using D3 solely for math means a significant amount of its (DOM-based) functionality is not available for use: selection.join, zoom, drag, brush, and transitions. Additionally, as mentioned above, D3 has its own learning curve and we would like developers to feel like they are writing native React code with standard APIs and familiar patterns.

“Why not just use one of the many existing React visualization libraries?”

In our research (Figure 1), we found that existing React visualization libraries are often high-level abstractions and optimized for ease of use (i.e., fewer lines of code) at the expense of expressivity. None offer the expressivity of D3 primitives and many don’t allow for the optimization we want in production because computation, animations, state management, styles, and rendering are all encapsulated.

Figure 1. Most web visualization libraries optimize for ease of use which can limit the expressivity of the possible output visualizations. visx is unique in supporting expressive, React visualization primitives.

Looking at the problem space in Figure 1, there is clearly an opportunity for a highly expressive React library to thrive. By creating low-level visualization primitives with a first-class React API, we hoped we could deliver learnability, expressiveness, and performance that any frontend developer could pick up. And visx was born 👶.

visx: Tell Me about It

visx (previously vx) stands for visualization components, and is a suite of over 30 separate packages of React visualization primitives that fall into several categories (Figure 2). It is un-opinionated on state management, animation, and styling so it can integrate with any React codebase, and its emphasis on modularity (similar to D3) lets you keep your bundle sizes down by only using the packages you need to create your reusable chart library or a custom one-off chart.

Figure 2. visx is a modular suite of 30+ separate packages that abstract solutions to common tasks in React visualization engineering.

FAQs

How does visx use D3?

Some packages use D3 for math and layout calculations, and functionally mirror the underlying D3 package with a declarative React API — like @visx/axis, @visx/geo, @visx/hierarchy, and @visx/shape. Other packages replace the DOM-manipulating functionality of D3 and bring first-class interaction primitives to React — such as @visx/brush, @visx/drag, and @visx/zoom.

What visualization “things” does it do that D3 doesn’t?

Many packages are entirely distinct from D3 and abstract solutions to common engineering problems we faced when building pixel-perfect visualizations in React. Many of these abstract and simplify challenging measurement tasks in React and simplify SVG APIs. Some specific examples:

@visx/tooltip (sandbox)

Tooltips are common visualization elements but implementing all of their microinteractions is hard. This package abstracts state management for tooltip content, coordinates, and visibility with React hooks (useTooltip) and Higher-Order Components (withTooltip). It also simplifies the complexities of tooltip rendering, such as auto-positioning so it is not clipped by its container, or optionally rendering inside a Portal to avoid z-index stacking context problems.

@visx/text (sandbox)

Compared to HTML text, which easily supports wrapping long text onto multiple lines with CSS properties, there is no native support for wrapping text in SVG 1.1. Implementing this in React, or even vanilla JavaScript, generally requires rendering invisible DOM elements to measure text size and calculate line splitting manually. This package abstracts this all away for you to make it easy to gracefully handle lengthy text in your visualizations.

@visx/responsive (sandbox)

Responsive web-apps are easy to create with HTML, but SVG- or canvas-based charts require pixel-based measurement which is not trivial in React. This package provides a variety of helpers to easily obtain screen or chart container dimensions in pixels so you can easily make your charts responsive.

@visx/gradient , @visx/pattern (sandbox)

Color gradients and pattern fills greatly expand the possible design space of charts and can uplevel or distinguish their aesthetic, but creating these style definitions in SVG is verbose and can be complicated. These packages greatly simplify the syntax for defining these styles to enable good-looking charts for the masses.

What can you do with visx?

We’ve been using visx for the past 2.5 years on dozens of internal data tools and Airbnb.com visualizations (Figure 3).