Custom Tooltips

Instead of using the pre-built tooltip functionality, you can pass a tooltip object to provide custom rendering for their chart.

By default, a CoralStackChart, for example, will render tooltips with a circle of the bar colour, followed by the label in whichever format has been provided:

01,0002,0003,0004,0005,0006,000000102030405060708
<CoralStackChart
  data={groupBarTemplateData}
  modifiers={{
      tooltip: {
          labelFormat: ({ datum }) => `${datum.y}kWh`,
      },
      chart: {
          domainPadding: { x: 40, y: 20 },
      },
      stack: {
          colorScale: [
              octopusTheme.color.action.error,
              octopusTheme.color.action.warning,
              octopusTheme.color.action.success,
          ],
      },
      xAxis: {
          fixTickLabelOverlap: false,
      }
  }}
/>

However, it's possible that you may want to create custom tooltips or tooltips that contain more information than the default.

Step 1

For example, you can adjust your data object so that it contains a labels object. The content of the object is free, so you can create key value pairs that are appropriate for your dataset.

export const groupBarTemplateData: ChartData[][] = [
  [
      { x: '00', y: 1000, labels: { group: 'Group 1', title: 'Title 1' } },
      { x: '01', y: 800, labels: { group: 'Group 2', title: 'Title 1' } },
      ...
  ],
  [
      { x: '00', y: 2300, labels: { group: 'Group 1', title: 'Title 2' } },
      { x: '01', y: 1100, labels: { group: 'Group 2', title: 'Title 2' } },
      ...
  ],
  [
      { x: '00', y: 1920, labels: { group: 'Group 1', title: 'Title 3' } },
      { x: '01', y: 0, labels: { group: 'Group 2', title: 'Title 3' } },
      ...
  ],
];

Step 2

Create a custom FlyOut object. You can set the type to CoralTooltipProps, and the function should pass down the following props:

  • activePoints: All the data points used to render the current stack or group
  • x: The x position of the tooltip that is rendered
  • y: The y position of the tooltip that is rendered
  • datum: The first item of the current data array
  • dx: Any horizontal shift from the x coordinate
  • dy: Any vertical shift from the y coordinate

You can also get index, data, verticalAnchor, textAnchor, angle, style, text and events props, which you can read about in the VictoryLabel documentation.

The following FlyOut object will list out all 3 data points with their respective title, output a single group title, and add a total count of the 3 data points in the Stack.

You will note that there's liberal use of !. This is because typescript believes these values can be undefined, though they never are in this instance. You will also need to manually set the x and y values by adding / subtracting from the standard x and y variables, as Victory will otherwise lay the labels out on top of each other.

const FlyOut = ({ activePoints, x, y, datum, dx, dy }: CoralTooltipProps) => {
  const total = activePoints!.reduce((acc, _) => acc + _.y, 0);

  return (
      <g>
          <rect
              x={x! - 30}
              y={y! - 50}
              width="110"
              dx={dx as number}
              dy={dy as number}
              height="90"
              rx="4.5"
              fill="rgba(0, 0, 0, 0.8)"
          />
          <text
              x={x! - 20}
              y={y! - 35}
              font-size="10"
              font-weight="bold"
              fill="white"
          >
              // @ts-ignore
              {`${datum.labels.group}`}
          </text>
          <text x={x! - 20} y={y! - 20} font-size="10" fill="white">
              {`Used ${total}kWh`}
          </text>
          {activePoints!.map((_, i) => {
              return (
                  <text
                      x={x! - 20}
                      y={y! + 14 * i}
                      font-size="10"
                      fill="white"
                  >
                      {`${_.labels.title} ${_.y}kWh`}
                  </text>
              );
          })}
      </g>
  );

};

The use of @ts-ignore on datum.labels.group is because we're extending the default datum to contain our additional labels object. You could pass it as below if you wanted to be more explicit.

<text
  ...
>
  {`${(datum as { labels: { group: string } }).labels.group}`}
</text>

Step 3

Finally, pass down your custom FlyOut component into the customFlyout property in your chart.

01,0002,0003,0004,0005,0006,000000102030405060708
<CoralStackChart
  data={groupBarTemplateData}
  modifiers={{
      ...
      stack: {
          ...,
          customFlyout: <FlyOut />
      },
      ...
  }}
/>