Percent Area Chart

import {
  Area,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  TooltipContentProps,
  TooltipValueType,
  createHorizontalChart,
  useRechartsTheme,
} from 'recharts';
import { generateMockData, MockDataType, RechartsDevtools } from '@recharts/devtools';

// #region Sample data and helper functions
const data = generateMockData(6, 198905);

const Typed = createHorizontalChart<MockDataType, string, number>()({ Area, XAxis, YAxis, Tooltip });

const toPercent = (decimal: number): string => `${(decimal * 100).toFixed(0)}%`;

const toNumber = (value: TooltipValueType | undefined): number => {
  if (typeof value === 'number') {
    return value;
  }
  let v;
  if (typeof value === 'string') {
    v = value;
  }
  if (Array.isArray(value)) {
    [, v] = value;
  }
  if (v == null) {
    return 0;
  }
  const parsed = parseFloat(String(v));
  if (!Number.isNaN(parsed)) {
    return parsed;
  }
  return 0;
};

const getPercent = (value: TooltipValueType | undefined, total: number): string => {
  const ratio = total > 0 ? toNumber(value) / total : 0;

  return toPercent(ratio);
};

// #endregion
const RenderTooltipContent = (o: TooltipContentProps<number, keyof MockDataType>) => {
  const theme = useRechartsTheme();
  const { payload, label } = o;
  const total = payload.reduce((result, entry) => result + Number(entry.value), 0);

  return (
    <div
      className="customized-tooltip-content"
      style={{
        ...theme?.typography,
        ...theme?.tooltip?.contentStyle,
        padding: '10px',
        borderRadius: '10px',
        boxShadow: '0 0 10px rgba(0,0,0,0.2)',
      }}
    >
      <h3 className="total">{`${label} (Total: ${total})`}</h3>
      <ul className="list">
        {payload.map((entry, index) => (
          <li key={`item-${index}`} style={{ color: entry.color }}>
            {`${entry.name}: ${entry.value}(${getPercent(entry.value, total)})`}
          </li>
        ))}
      </ul>
    </div>
  );
};

const PercentAreaChart = () => {
  return (
    <Typed.AreaChart
      style={{ width: '100%', maxWidth: '700px', maxHeight: '70vh', aspectRatio: 1.618 }}
      responsive
      data={data}
      stackOffset="expand"
      margin={{
        top: 10,
        right: 20,
        left: 0,
        bottom: 0,
      }}
    >
      <CartesianGrid />
      <Typed.XAxis dataKey="label" />
      <Typed.YAxis tickFormatter={toPercent} width="auto" />
      <Typed.Tooltip content={RenderTooltipContent} />
      <Typed.Area type="monotone" dataKey="x" stackId="1" />
      <Typed.Area type="monotone" dataKey="y" stackId="1" />
      <Typed.Area type="monotone" dataKey="z" stackId="1" />
      <RechartsDevtools />
    </Typed.AreaChart>
  );
};

export default PercentAreaChart;