@visx/annotation

SVG Annotations enable you to label points, thresholds, or regions of a visualization to provide additional context to for your chart consumer. This package is heavily inspired by Susie Lu's react-annotation library.

Each annotation consists of three (optional) parts:

  1. Subject (CircleSubject, LineSubject, more ๐Ÿ”œ) โ€“ what part of a chart is being annotated (point, line, region)

  2. Label โ€“ย the text component for the annotation. Handles SVG text wrapping using @visx/text, and supports title and subtitle customization as well as vertical & horizontal anchors / alignment

  3. Connector โ€“ line connecting a subject and label

The Annotation or EditableAnnotation component wrappers allow you to compose these components and simplify their individual positioning:

<EditableAnnotation
  x={subjectX}
  y={subjectY}
  dx={labelDx} // x offset of label from subject
  dy={labelDy} // y offset of label from subject
  onDragEnd={({ x, y, dx, dy }) => ...}
>
  <Connector />
  <CircleSubject />
  <Label title="Context about this point" subtitle="More deets">
</EditableAnnotation>

Components can also be used in isolation, in which case you must specify exact positions for each item:

() => (
  <g>
    <Connector x={subjectX} y={subjectY} dx={labelDx} dy={labelDy} />
    <CircleSubject x={subjectX} y={subjectY} />
    <Label x={subjectX + labelDx} y={subjectY + labelDy} title="...">
  </g>
)
โš ๏ธ ResizeObserver dependency

The Label component relies on ResizeObservers for auto-sizing. If you need a polyfill, you can either polute the window object or inject it cleanly through props:

import { ResizeObserver } from 'your-favorite-polyfill';

function App() {
  return <Label resizeObserverPolyfill={ResizeObserver} {...} />

Installation

npm install --save @visx/annotation

Examples

APIs

#<Annotation />

# childrenReactNoderequired

Annotation children (Subject, Label, Connector)

# dxnumber

x delta of the Label from the Subject.

# dynumber

y delta of the Label from the Subject.

# xnumber

x position of the Subject.

# ynumber

y position of the Subject.

#<EditableAnnotation />

# childrenReactNoderequired

Annotation children (Subject, Label, Connector)

# heightnumberrequired

Height of the possible drag canvas (e.g., SVG container).

# widthnumberrequired

Width of the possible drag canvas (e.g., SVG container).

# canEditLabelboolean

Whether the Label position (dx, dy) is editable.

Default true

# canEditSubjectboolean

Whether the Subject position (x, y) is editable.

Default true

# dxnumber

x delta of the Label from the Subject.

# dynumber

y delta of the Label from the Subject.

# labelDragHandlePropsSVGProps<SVGCircleElement>

Optional circle props to set on the label drag handle.

# onDragEnd({ x, y, dx, dy, event }: HandlerArgs) => void

Callback invoked on drag end.

# onDragMove({ x, y, dx, dy, event }: HandlerArgs) => void

Callback invoked on drag move.

# onDragStart({ x, y, dx, dy, event }: HandlerArgs) => void

Callback invoked on drag start.

# subjectDragHandlePropsSVGProps<SVGCircleElement>

Optional circle props to set on the subject drag handle.

# xnumber

x position of the Subject.

# ynumber

y position of the Subject.

#<CircleSubject />

# classNamestring

Optional className to apply to CircleSubject in addition to 'visx-annotation-subject'.

# radiusnumber

Radius of CircleSubject.

Default 16

# strokestring

Color of CircleSubject.

Default #222

# xnumber

x position of the Subject.

# ynumber

y position of the Subject.

#<LineSubject />

# maxnumberrequired

The maximum coordinate of the line.

# minnumberrequired

The minimum coordinate of the line.

# classNamestring

Optional className to apply to LineSubject in addition to 'visx-annotation-subject'.

# orientation"horizontal" | "vertical"

Orientation of line.

Default vertical

# strokestring

Color of LineSubject.

Default #222

# strokeWidthnumber

strokeWidth of LineSubject.

# xnumber

x position of LineSubject (for vertical LineSubjects).

# ynumber

y position of LineSubject (for horizontal LineSubjects).

#<Connector />

# classNamestring

Optional className to apply to container in addition to 'visx-annotation-connector'.

# dxnumber

x delta of the Label from the Subject.

# dynumber

y delta of the Label from the Subject.

# pathPropsSVGProps<SVGPathElement>

Optional additional props.

# strokestring

Color of the connector line.

Default #222

# type"line" | "elbow"

Connector type.

Default elbow

# xnumber

x position of the Subject.

# ynumber

y position of the Subject.

#<Label />

# anchorLineStrokestring

Stroke color of anchor line.

Default #222

# backgroundFillstring

Background color of label.

Default #eaeaea

# backgroundPaddingnumber | { top?: number; right?: number; bottom?: number; left?: number; }

Padding of text from background.

# backgroundPropsSVGProps<SVGRectElement>

Additional props to be passed to background SVGRectElement.

# classNamestring

Optional className to apply to container in addition to 'visx-annotation-label'.

# fontColorstring

Color of title and subtitle text.

Default #222

# horizontalAnchor"end" | "middle" | "inherit" | "start"

Whether the label is horizontally anchored to the start, middle, or end of its x position.

# maxWidthnumber

Max width of annotation, including background, for text wrapping.

Default 125

# resizeObserverPolyfillnew (cb: ResizeObserverCallback) => ResizeObserver

Optionally inject a ResizeObserver polyfill, else this must be globally available.

# showAnchorLineboolean

Whether to render a line indicating label text anchor.

Default true

# showBackgroundboolean

Whether to render a label background.

Default true

# subtitlestring

Optional subtitle.

# subtitleDynumber

The vertical offset of the subtitle from the title.

Default 4

# subtitleFontSizeReactText

Optional title font size.

Default 12

# subtitleFontWeightReactText

Optional title font weight.

Default 200

# subtitlePropsPartial<TextProps>

Optional subtitle Text props (to override color, etc.).

# titlestring

Optional title.

# titleFontSizeReactText

Optional title font size.

Default 16

# titleFontWeightReactText

Optional title font weight.

Default 600

# titlePropsPartial<TextProps>

Optional title Text props (to override color, etc.).

# verticalAnchor"end" | "middle" | "start"

Whether the label is vertically anchored to the start, middle, or end of its y position.

# widthnumber

Width of annotation, including background, for text wrapping.

# xnumber

Left offset of entire AnnotationLabel, if not specified uses x + dx from Annotation.

# ynumber

Top offset of entire AnnotationLabel, if not specified uses y + dy from Annotation.

#<HtmlLabel />

# anchorLineStrokestring

Stroke color of anchor line.

Default #222

# childrenReactNode

Pass in a custom element as the label to style as you like. Renders inside a <foreignObject>, be aware that most non-browser SVG renderers will not render HTML <foreignObject>s. See: https://github.com/airbnb/visx/issues/1173#issuecomment-1014380545.

# classNamestring

Optional className to apply to container in addition to 'visx-annotation-label'.

# containerStyleCSSProperties

Optional styles to apply to the HTML container.

# horizontalAnchor"end" | "middle" | "inherit" | "start"

Whether the label is horizontally anchored to the start, middle, or end of its x position.

# resizeObserverPolyfillnew (cb: ResizeObserverCallback) => ResizeObserver

Optionally inject a ResizeObserver polyfill, else this must be globally available.

# showAnchorLineboolean

Whether to render a line indicating label text anchor.

Default true

# verticalAnchor"end" | "middle" | "start"

Whether the label is vertically anchored to the start, middle, or end of its y position.

# xnumber

Left offset of entire AnnotationLabel, if not specified uses x + dx from Annotation.

# ynumber

Top offset of entire AnnotationLabel, if not specified uses y + dy from Annotation.