npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@visx/xychart

v3.12.0

Published

Composable cartesian coordinate chart built with visx primitives

Downloads

752,345

Readme

@visx/xychart

In contrast to other visx packages which are low-level, this package seeks to abstract some of the complexity of common visualization engineering, and exposes a high-level x,y (cartesian coordinate) chart API. However, it is implemented using modularized React.context layers for theme, canvas dimensions, x/y/color scales, data, events, and tooltips which allows for more expressivity and advanced use cases.

Out of the box it supports the following:

  • * many common <*Series /> types (animated or not) such as lines, bars, etc.
  • * <Axis /> (animated or not)
  • * <Grid /> (animated or not)
  • * <Annotation /> (animated or not)
  • * <Tooltip />
  • * themeing

The following illustrates basic usage to create an animated line chart with a bottom Axis, Grid, and Tooltip:

import {
  AnimatedAxis, // any of these can be non-animated equivalents
  AnimatedGrid,
  AnimatedLineSeries,
  XYChart,
  Tooltip,
} from '@visx/xychart';

const data1 = [
  { x: '2020-01-01', y: 50 },
  { x: '2020-01-02', y: 10 },
  { x: '2020-01-03', y: 20 },
];

const data2 = [
  { x: '2020-01-01', y: 30 },
  { x: '2020-01-02', y: 40 },
  { x: '2020-01-03', y: 80 },
];

const accessors = {
  xAccessor: (d) => d.x,
  yAccessor: (d) => d.y,
};

const render = () => (
  <XYChart height={300} xScale={{ type: 'band' }} yScale={{ type: 'linear' }}>
    <AnimatedAxis orientation="bottom" />
    <AnimatedGrid columns={false} numTicks={4} />
    <AnimatedLineSeries dataKey="Line 1" data={data1} {...accessors} />
    <AnimatedLineSeries dataKey="Line 2" data={data2} {...accessors} />
    <Tooltip
      snapTooltipToDatumX
      snapTooltipToDatumY
      showVerticalCrosshair
      showSeriesGlyphs
      renderTooltip={({ tooltipData, colorScale }) => (
        <div>
          <div style={{ color: colorScale(tooltipData.nearestDatum.key) }}>
            {tooltipData.nearestDatum.key}
          </div>
          {accessors.xAccessor(tooltipData.nearestDatum.datum)}
          {', '}
          {accessors.yAccessor(tooltipData.nearestDatum.datum)}
        </div>
      )}
    />
  </XYChart>
);

See sections below for more detailed guidance and advanced usage, or explore the comprehensive API below.

Basic usage

npm install --save @visx/xychart react-spring

Note: react-spring is a required peerDependency for importing Animated* components.

The following Series types are currently supported and we are happy to review or consider additional Series types in the future.

| Component name | Description | Usage | | --------------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------- | --- | | (Animated)AreaSeries | Connect data points with a <path />, with a color fill to the zero baseline | <AreaSeries /> | | (Animated)BarSeries | Render a <rect /> for each data point | <BarSeries /> | | (Animated)BarGroup | Group multiple child <BarSeries /> values together | <BarGroup><BarSeries /><BarSeries />...</BarGroup> | | (Animated)BarStack | Stack multiple child <BarSeries /> values together | <BarStack><BarSeries /><BarSeries />...</BarStack> | | | (Animated)GlyphSeries | Render a Glyph (any shape, defaults to <circle />) for each data point, e.g., a scatter plot | <GlyphSeries renderGlyph={() => ...} /> | | (Animated)LineSeries | Connect data points with a <path> | <GlyphSeries /> |

All Series have animated and non-animated variants to give you more control over your bundle size, support missing (null) data, and can be rendered vertically or horizontally.

Default lightTheme and darkTheme themes are exported from @visx/xychart and the utility buildChartTheme is exported to support easy creation of custom themes.

import { buildChartTheme, XYChart } from '@visx/xychart';
import { TextProps as SVGTextProps } from '@visx/text/lib/Text'; // just for types

const customTheme = buildChartTheme({
  // colors
  backgroundColor: string, // used by Tooltip, Annotation
  colors: string[], // categorical colors, mapped to series via `dataKey`s

  // labels
  svgLabelBig?: SVGTextProps,
  svgLabelSmall?: SVGTextProps,
  htmlLabel?: HTMLTextStyles,

  // lines
  xAxisLineStyles?: LineStyles,
  yAxisLineStyles?: LineStyles,
  xTickLineStyles?: LineStyles,
  yTickLineStyles?: LineStyles,
  tickLength: number,

  // grid
  gridColor: string,
  gridColorDark: string, // used for axis baseline if x/yxAxisLineStyles not set
  gridStyles?: CSSProperties,
});

() => <XYChart theme={customTheme} />

@visx/tooltip Tooltips are integrated into @visx/xychart, and should be rendered as a child of XYChart (or a child where TooltipContext is provided).

Tooltip positioning is handled by the Tooltip itself, based on TooltipContext. Tooltip is rendered inside a Portal, avoiding clipping by parent DOM elements with higher z-index contexts. See the API below for a full list of props to support additional behavior, such as snapping to data point positions and rendering cross-hairs.

Tooltip content is controlled by the specified prop.renderTooltip which has access to:

  • tooltipData.nearestDatum – the globally closest Datum, across all Series's dataKeys
  • tooltipData.datumByKey – the closest Datum for each Series's dataKey; this enables "shared tooltips" where you can render the nearest data point for each Series.
  • a shared colorScale which maps Series's dataKeys to theme colors

The following PointerEvents (handling both MouseEvents and TouchEvents) are currently supported. They may be set on individual Series components (e.g., <BarSeries onPointerMove={() => ...} />), or at the chart level (e.g., <XYChart onPointerMove={() => {}} />) in which case they are invoked once for every *Series. To disable event emitting for any Series set <*Series enableEvents=false />. The onFocus/onBlur handlers enable you to make your chart events and Tooltips accessible via keyboard interaction. Note that the current implementation requires your target browser to support the SVG 2.0 spec for tabIndex on SVG elements.

Below, HandlerParms has the following type signature:

type EventHandlerParams<Datum> = {
  datum: Datum; // nearest Datum to event, for Series with `dataKey=key`
  distanceX: number; // x distance between event and Datum, in px
  distanceY;: number; // y distance between event and Datum, in px
  event: React.PointerEvent | React.FocusEvent; // the event
  index: number; // index of Datum in Series `data` array
  key: string; // `dataKey` of Series to which `Datum` belongs
  svgPoint: { x: number; y: number }; // event position in svg-coordinates
};

| Prop name | Signature | XYChart support | *Series support | | --------------- | --------------------------------------------- | ----------------- | ----------------- | | onPointerMove | (params: EventHandlerParams<Datum>) => void | ✅ | ✅ | | onPointerOut | (event: React.PointerEvent) => void | ✅ | ✅ | | onPointerUp | (params: EventHandlerParams<Datum>) => void | ✅ | ✅ | | onPointerDown | (params: EventHandlerParams<Datum>) => void | ✅ | ✅ | | onFocus | (params: EventHandlerParams<Datum>) => void | ❌ | ✅ | | onBlur | (event: React.TouchEvent) => void | ❌ | ✅ |

Composable @visx/annotations annotations are integrated into @visx/xychart and use its theme and dimension context. These components allow for annotation of individual points using AnnotationCircleSubject, or x- or y-thresholds using AnnotationLineSubject.

CodeSandbox

import React from 'react';
import {
  Annotation,
  AnnotationLabel,
  AnnotationConnector,
  AnnotationCircleSubject,
  Grid,
  LineSeries,
  XYChart,
} from '@visx/xychart';

const data = [
  { x: '2020-01-01', y: 50 },
  { x: '2020-01-02', y: 10 },
  { x: '2020-01-03', y: 20 },
  { x: '2020-01-04', y: 5 },
];

const labelXOffset = -40;
const labelYOffset = -50;
const chartConfig = {
  xScale: { type: 'band' },
  yScale: { type: 'linear' },
  height: 300,
  margin: { top: 10, right: 10, bottom: 10, left: 10 },
};

export default () => (
  <XYChart {...chartConfig}>
    <Grid numTicks={3} />
    <LineSeries dataKey="line" data={data} xAccessor={d => d.x} yAccessor={d => d.y} />
    <Annotation
      dataKey="line" // use this Series's accessor functions, alternatively specify x/yAccessor here
      datum={data[2]}
      dx={labelXOffset}
      dy={labelYOffset}
    >
      {/** Text label */}
      <AnnotationLabel
        title="Title"
        subtitle="Subtitle deets"
        showAnchorLine={false}
        backgroundFill="rgba(0,150,150,0.1)"
      />
      {/** Draw circle around point */}
      <AnnotationCircleSubject />
      {/** Connect label to CircleSubject */}
      <AnnotationConnector />
    </AnimatedAnnotation>
  </XYChart>
);
⚠️ ResizeObserver dependency

Responsive XYCharts, Tooltip, and AnnotationLabel components rely on ResizeObservers. If your browser target needs a polyfill, you can either pollute the window object or inject it cleanly using the resizeObserverPolyfill prop for these components. A polyfill passed to XYChart will be accessible to child Tooltip and AnnotationLabel components.

Error: This browser does not support ResizeObserver out of the box

// no polyfill, no browser support
() => <XYChart {...} />
() => <XYChart {...}><Tooltip /></XYChart>

✅ No errors

// no polyfill, target browser supports ResizeObserver
() => <XYChart {...} />
() => <XYChart {...}><Tooltip /></XYChart>

// import the polyfill in the needed module, or set it on `window` object
import ResizeObserver from 'resize-observer-polyfill';
() => <XYChart {...}><Tooltip /></XYChart> // 😎

// cleanly pass polyfill to component that needs it
import ResizeObserver from 'resize-observer-polyfill';
() => (
  <XYChart resizeObserverPolyfill={ResizeObserver} {...}>
    <Tooltip />
  </XYChart>
)

Advanced usage

XYChart is implemented using modularized React.context layers for scales, canvas dimensions, data, events, and tooltips which enables more advanced usage than many other chart-level abstractions.

By default XYChart renders all context providers if a given context is not available, but you can share context across multiple XYCharts to implement functionality such as linked tooltips, shared themes, or shared data.

This context provides chart canvas dimensions (width, height, and margin), x/y/color scales, and a data registry. The data registry includes data from all child *Series, and x/y/color scales are updated accordingly accounting for canvas dimensions.

This context provides an XYChart theme, its used by all visual elements that compose a chart, and can be used to render custom visual elements that are on theme.

This context provides an event publishing / subscription object which can be used via the useEventEmitter hook. Series and XYChart events, including tooltip updates, are emitted and handled with through this context.

CodeSandbox

import React, { useState } from 'react';
import { useEventEmitter, EventEmitterProvider } from '@visx/xychart';

const eventSourceId = 'optional-source-id-filter';

const EmitEvent = () => {
  const emit = useEventEmitter();
  return (
    <button onPointerUp={(event) => emit('pointerup', event, eventSourceId)}>emit event</button>
  );
};

const SubscribeToEvent = () => {
  const [clickCount, setClickCount] = useState(0);
  const allowedEventSources = [eventSourceId];
  useEventEmitter('pointerup', () => setClickCount(clickCount + 1), allowedEventSources);

  return <div>Emitted {clickCount} events</div>;
};

export default function Example() {
  return (
    <EventEmitterProvider>
      <EmitEvent />
      <SubscribeToEvent />
    </EventEmitterProvider>
  );
}

This context provides access to @visx/tooltips useTooltip state, including whether the tooltip is visible (tooltipOpen), tooltlip position (tooltipLeft, tooltipTop), tooltipData: { nearestDatum, datumByKey } described above, and functions to update context (hideTooltip, showTooltip, and updateTooltip).