Hafiz Temuri
Hafiz Temuri

Reputation: 4112

Recharts - How to have two different tooltips for Line and Bar chart

I want to have two different tooltips when someone hovers the line and the bar. By default Tooltip component considers both as same, but they are two different kind of data. That is why I want to have a separate tooltip for each depending on what the user hovers.

I am trying to figure this out for Line chart first, and I am sure it will be the same for Bar chart. I am using activeDot object to know which dot the user is hovering over. Although it triggers the onMouseOver function, but it contains no data to know which dot it is. Is there anything I could do to have the data as customized Tooltip content has (CustomizedTooltip in my code). Such as, label, payload and etc.

Here is what I have so far, CodeSandBox

Upvotes: 3

Views: 8811

Answers (2)

Revan99
Revan99

Reputation: 446

you can add ternary operator aka conditional rendering something like this :

<Tooltip cursor={false} content={type===line?<CustomizedTooltip chartType={this.state.chartType}/>:<CustomizedTooltipBar chartType={this.state.chartType}/>} />

Upvotes: 0

Mayank
Mayank

Reputation: 158

The idea here is to maintain a state of chart for which you want to show the tooltip.

Then update the state onMouseOver and reset the state on onMouseLeave.

Please find your update code at CodeSandBox

import * as React from "react";
import { render } from "react-dom";
import {
  ResponsiveContainer,
  ComposedChart,
  Line,
  Bar,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend
} from "recharts";

const data = [
  { name: "" },
  { name: "Monday", uv: 265, pv: 800 },
  { name: "Tuesday", uv: 475, pv: 967 },
  { name: "Wednesday", uv: 624, pv: 1098 },
  { name: "Thursday", uv: 856, pv: 1200 },
  { name: "Friday", uv: 1024, pv: 1108 },
  { name: "Saturday", uv: 1116, pv: 1220 },
  { name: "Sunday", uv: 1208, pv: 1358 },
  { name: "" }
];

const formatter = (value: string) => `$${value}`;

class CustomizedTooltip extends React.PureComponent<any> {
  render() {
    const { label, payload, active, chartType } = this.props;

    if (!active || !label || payload.length === 0) return null;

    return (
      <div className="i-will-customize-tooltip-later">
        <p className="label">{`${label} : ${payload[chartType].value}`}</p>
      </div>
    );
  }
}

class CustomizedDot extends React.PureComponent<any> {
  render() {
    const { cx, cy, value } = this.props;

    if (!value) {
      return null;
    }

    return (
      <svg
        x={cx - 5}
        y={cy - 5}
        width={10}
        height={10}
        viewBox="0 0 10 10"
        fill="#ff7385"
      >
        <rect width="10" height="10" />
      </svg>
    );
  }
}

class LineBarAreaComposedChart extends React.PureComponent<any, any> {
  constructor(){
    super({})
    this.state = {
      chartType: 0
    }
  }
  render() {
    return (
      <ResponsiveContainer minHeight={500}>
        <ComposedChart
          width={800}
          height={400}
          data={data}
          margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
        >
          <CartesianGrid stroke="#efefef" vertical={false} />
          <XAxis
            dataKey="name"
            type="category"
            axisLine={false}
            tickLine={false}
          />
          <YAxis
            dataKey="pv"
            tickFormatter={formatter}
            type="number"
            axisLine={false}
            tickLine={false}
          />
          <Tooltip cursor={false} content={<CustomizedTooltip chartType={this.state.chartType}/>} />
          <Legend />
          <Bar name="Donation total" dataKey="pv" barSize={80} fill="#48bbee" />
          <Line
            name="Average dontaion trend"
            type="monotone"
            dataKey="uv"
            data={data}
            stroke="#ff7385"
            dot={<CustomizedDot />}
            activeDot={{
              onMouseOver: (e: any) => this.setState({chartType: 1}),
              onMouseLeave: (e: any) => this.setState({chartType: 0})
            }}
          />
        </ComposedChart>
      </ResponsiveContainer>
    );
  }
}

render(<LineBarAreaComposedChart />, document.getElementById("root"));

Upvotes: 4

Related Questions